Esempio n. 1
0
        /// <summary>
        /// Validates the png header.
        /// </summary>
        /// <exception cref="NotSupportedException">
        /// Thrown if the image does pass validation.
        /// </exception>
        private void ValidateHeader()
        {
            if (!ColorTypes.ContainsKey(this.header.ColorType))
            {
                throw new NotSupportedException("Color type is not supported or not valid.");
            }

            if (!ColorTypes[this.header.ColorType].Contains(this.header.BitDepth))
            {
                throw new NotSupportedException("Bit depth is not supported or not valid.");
            }

            if (this.header.FilterMethod != 0)
            {
                throw new NotSupportedException("The png specification only defines 0 as filter method.");
            }

            if (this.header.InterlaceMethod != 0)
            {
                // TODO: Support interlacing
                throw new NotSupportedException("Interlacing is not supported.");
            }

            this.PngColorType = (PngColorType)this.header.ColorType;
        }
Esempio n. 2
0
        private static void TestPngEncoderCore <TPixel>(
            TestImageProvider <TPixel> provider,
            PngColorType pngColorType,
            PngFilterMethod pngFilterMethod,
            int compressionLevel        = 6,
            int paletteSize             = 255,
            bool appendPngColorType     = false,
            bool appendPngFilterMethod  = false,
            bool appendPixelType        = false,
            bool appendCompressionLevel = false,
            bool appendPaletteSize      = false)
            where TPixel : struct, IPixel <TPixel>
        {
            using (Image <TPixel> image = provider.GetImage())
            {
                if (!HasAlpha(pngColorType))
                {
                    image.Mutate(c => c.MakeOpaque());
                }

                var encoder = new PngEncoder
                {
                    PngColorType     = pngColorType,
                    PngFilterMethod  = pngFilterMethod,
                    CompressionLevel = compressionLevel,
                    Quantizer        = new WuQuantizer(paletteSize)
                };

                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 debugInfo            = $"{pngColorTypeInfo}{pngFilterMethodInfo}{compressionLevelInfo}{paletteSizeInfo}";
                //string referenceInfo = $"{pngColorTypeInfo}";

                // Does DebugSave & load reference CompareToReferenceInput():
                string actualOutputFile = ((ITestImageProvider)provider).Utility.SaveTestOutputFile(image, "png", encoder, debugInfo, appendPixelType);

                if (TestEnvironment.IsMono)
                {
                    // There are bugs in mono's System.Drawing implementation, reference decoders are not always reliable!
                    return;
                }

                IImageDecoder referenceDecoder    = TestEnvironment.GetReferenceDecoder(actualOutputFile);
                string        referenceOutputFile = ((ITestImageProvider)provider).Utility.GetReferenceOutputFileName("png", debugInfo, appendPixelType, true);

                using (var actualImage = Image.Load <TPixel>(actualOutputFile, referenceDecoder))
                    using (var referenceImage = Image.Load <TPixel>(referenceOutputFile, referenceDecoder))
                    {
                        float paletteToleranceHack = 80f / paletteSize;
                        paletteToleranceHack = paletteToleranceHack * paletteToleranceHack;
                        ImageComparer comparer = pngColorType == PngColorType.Palette
                                                 ? ImageComparer.Tolerant(ToleranceThresholdForPaletteEncoder * paletteToleranceHack)
                                                 : ImageComparer.Exact;

                        comparer.VerifySimilarity(referenceImage, actualImage);
                    }
            }
        }
Esempio n. 3
0
        static PixelFormat MakePixelFormat(byte bitDepth, PngColorType colorType)
        {
            if (bitDepth == 8 && colorType == (PngColorType.Indexed | PngColorType.Color))
            {
                return(PixelFormat.Format8bppIndexed);
            }

            throw new InvalidDataException("Unknown pixel format");
        }
Esempio n. 4
0
        public void Encode_WithPngTransparentColorBehaviorClear_Works(PngColorType colorType)
        {
            // arrange
            var image   = new Image <Rgba32>(50, 50);
            var encoder = new PngEncoder()
            {
                TransparentColorMode = PngTransparentColorMode.Clear,
                ColorType            = colorType
            };
            Rgba32 rgba32 = Color.Blue;

            for (int y = 0; y < image.Height; y++)
            {
                System.Span <Rgba32> rowSpan = image.GetPixelRowSpan(y);

                // Half of the test image should be transparent.
                if (y > 25)
                {
                    rgba32.A = 0;
                }

                for (int x = 0; x < image.Width; x++)
                {
                    rowSpan[x].FromRgba32(rgba32);
                }
            }

            // act
            using var memStream = new MemoryStream();
            image.Save(memStream, encoder);

            // assert
            memStream.Position = 0;
            using var actual   = Image.Load <Rgba32>(memStream);
            Rgba32 expectedColor = Color.Blue;

            if (colorType == PngColorType.Grayscale || colorType == PngColorType.GrayscaleWithAlpha)
            {
                var luminance = ColorNumerics.Get8BitBT709Luminance(expectedColor.R, expectedColor.G, expectedColor.B);
                expectedColor = new Rgba32(luminance, luminance, luminance);
            }

            for (int y = 0; y < actual.Height; y++)
            {
                System.Span <Rgba32> rowSpan = actual.GetPixelRowSpan(y);

                if (y > 25)
                {
                    expectedColor = Color.Transparent;
                }

                for (int x = 0; x < actual.Width; x++)
                {
                    Assert.Equal(expectedColor, rowSpan[x]);
                }
            }
        }
Esempio n. 5
0
        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);
                    }
            }
        }
Esempio n. 6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PngEncoderCore"/> class.
 /// </summary>
 /// <param name="memoryManager">The <see cref="MemoryManager"/> to use for buffer allocations.</param>
 /// <param name="options">The options for influencing the encoder</param>
 public PngEncoderCore(MemoryManager memoryManager, IPngEncoderOptions options)
 {
     this.memoryManager    = memoryManager;
     this.pngColorType     = options.PngColorType;
     this.compressionLevel = options.CompressionLevel;
     this.gamma            = options.Gamma;
     this.quantizer        = options.Quantizer;
     this.threshold        = options.Threshold;
     this.writeGamma       = options.WriteGamma;
 }
Esempio n. 7
0
        public void Encode_PreserveTrns(string imagePath, PngBitDepth pngBitDepth, PngColorType pngColorType)
        {
            var options = new PngEncoder();

            var testFile = TestFile.Create(imagePath);

            using (Image <Rgba32> input = testFile.CreateImage())
            {
                PngMetadata inMeta = input.Metadata.GetFormatMetadata(PngFormat.Instance);
                Assert.True(inMeta.HasTrans);

                using (var memStream = new MemoryStream())
                {
                    input.Save(memStream, options);
                    memStream.Position = 0;
                    using (var output = Image.Load <Rgba32>(memStream))
                    {
                        PngMetadata outMeta = output.Metadata.GetFormatMetadata(PngFormat.Instance);
                        Assert.True(outMeta.HasTrans);

                        switch (pngColorType)
                        {
                        case PngColorType.Grayscale:
                            if (pngBitDepth.Equals(PngBitDepth.Bit16))
                            {
                                Assert.True(outMeta.TransparentGray16.HasValue);
                                Assert.Equal(inMeta.TransparentGray16, outMeta.TransparentGray16);
                            }
                            else
                            {
                                Assert.True(outMeta.TransparentGray8.HasValue);
                                Assert.Equal(inMeta.TransparentGray8, outMeta.TransparentGray8);
                            }

                            break;

                        case PngColorType.Rgb:
                            if (pngBitDepth.Equals(PngBitDepth.Bit16))
                            {
                                Assert.True(outMeta.TransparentRgb48.HasValue);
                                Assert.Equal(inMeta.TransparentRgb48, outMeta.TransparentRgb48);
                            }
                            else
                            {
                                Assert.True(outMeta.TransparentRgb24.HasValue);
                                Assert.Equal(inMeta.TransparentRgb24, outMeta.TransparentRgb24);
                            }

                            break;
                        }
                    }
                }
            }
        }
Esempio n. 8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PngEncoderCore"/> class.
 /// </summary>
 /// <param name="options">The options for influencing the encoder</param>
 public PngEncoderCore(IPngEncoderOptions options)
 {
     this.ignoreMetadata   = options.IgnoreMetadata;
     this.paletteSize      = options.PaletteSize > 0 ? options.PaletteSize.Clamp(1, int.MaxValue) : int.MaxValue;
     this.pngColorType     = options.PngColorType;
     this.compressionLevel = options.CompressionLevel;
     this.gamma            = options.Gamma;
     this.quantizer        = options.Quantizer;
     this.threshold        = options.Threshold;
     this.writeGamma       = options.WriteGamma;
 }
Esempio n. 9
0
        /// <inheritdoc />
        public async Task <Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken)
        {
            PngDecoderCore decoder = new(configuration, true);
            IImageInfo     info    = await decoder.IdentifyAsync(configuration, stream, cancellationToken).ConfigureAwait(false);

            stream.Position = 0;

            PngMetadata  meta  = info.Metadata.GetPngMetadata();
            PngColorType color = meta.ColorType.GetValueOrDefault();
            PngBitDepth  bits  = meta.BitDepth.GetValueOrDefault();

            switch (color)
            {
            case PngColorType.Grayscale:
                if (bits == PngBitDepth.Bit16)
                {
                    return(!meta.HasTransparency
                            ? await this.DecodeAsync <L16>(configuration, stream, cancellationToken).ConfigureAwait(false)
                            : await this.DecodeAsync <La32>(configuration, stream, cancellationToken).ConfigureAwait(false));
                }

                return(!meta.HasTransparency
                        ? await this.DecodeAsync <L8>(configuration, stream, cancellationToken).ConfigureAwait(false)
                        : await this.DecodeAsync <La16>(configuration, stream, cancellationToken).ConfigureAwait(false));

            case PngColorType.Rgb:
                if (bits == PngBitDepth.Bit16)
                {
                    return(!meta.HasTransparency
                            ? await this.DecodeAsync <Rgb48>(configuration, stream, cancellationToken).ConfigureAwait(false)
                            : await this.DecodeAsync <Rgba64>(configuration, stream, cancellationToken).ConfigureAwait(false));
                }

                return(!meta.HasTransparency
                        ? await this.DecodeAsync <Rgb24>(configuration, stream, cancellationToken).ConfigureAwait(false)
                        : await this.DecodeAsync <Rgba32>(configuration, stream, cancellationToken).ConfigureAwait(false));

            case PngColorType.Palette:
                return(await this.DecodeAsync <Rgba32>(configuration, stream, cancellationToken).ConfigureAwait(false));

            case PngColorType.GrayscaleWithAlpha:
                return((bits == PngBitDepth.Bit16)
                        ? await this.DecodeAsync <La32>(configuration, stream, cancellationToken).ConfigureAwait(false)
                        : await this.DecodeAsync <La16>(configuration, stream, cancellationToken).ConfigureAwait(false));

            case PngColorType.RgbWithAlpha:
                return((bits == PngBitDepth.Bit16)
                        ? await this.DecodeAsync <Rgba64>(configuration, stream, cancellationToken).ConfigureAwait(false)
                        : await this.DecodeAsync <Rgba32>(configuration, stream, cancellationToken).ConfigureAwait(false));

            default:
                return(await this.DecodeAsync <Rgba32>(configuration, stream, cancellationToken).ConfigureAwait(false));
            }
        }
Esempio n. 10
0
        /// <inheritdoc />
        public Image Decode(Configuration configuration, Stream stream)
        {
            PngDecoderCore decoder = new(configuration, true);
            IImageInfo     info    = decoder.Identify(configuration, stream);

            stream.Position = 0;

            PngMetadata  meta  = info.Metadata.GetPngMetadata();
            PngColorType color = meta.ColorType.GetValueOrDefault();
            PngBitDepth  bits  = meta.BitDepth.GetValueOrDefault();

            switch (color)
            {
            case PngColorType.Grayscale:
                if (bits == PngBitDepth.Bit16)
                {
                    return(!meta.HasTransparency
                            ? this.Decode <L16>(configuration, stream)
                            : this.Decode <La32>(configuration, stream));
                }

                return(!meta.HasTransparency
                        ? this.Decode <L8>(configuration, stream)
                        : this.Decode <La16>(configuration, stream));

            case PngColorType.Rgb:
                if (bits == PngBitDepth.Bit16)
                {
                    return(!meta.HasTransparency
                            ? this.Decode <Rgb48>(configuration, stream)
                            : this.Decode <Rgba64>(configuration, stream));
                }

                return(!meta.HasTransparency
                        ? this.Decode <Rgb24>(configuration, stream)
                        : this.Decode <Rgba32>(configuration, stream));

            case PngColorType.Palette:
                return(this.Decode <Rgba32>(configuration, stream));

            case PngColorType.GrayscaleWithAlpha:
                return((bits == PngBitDepth.Bit16)
                    ? this.Decode <La32>(configuration, stream)
                    : this.Decode <La16>(configuration, stream));

            case PngColorType.RgbWithAlpha:
                return((bits == PngBitDepth.Bit16)
                    ? this.Decode <Rgba64>(configuration, stream)
                    : this.Decode <Rgba32>(configuration, stream));

            default:
                return(this.Decode <Rgba32>(configuration, stream));
            }
        }
Esempio n. 11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PngEncoderCore"/> class.
 /// </summary>
 /// <param name="memoryAllocator">The <see cref="MemoryAllocator"/> to use for buffer allocations.</param>
 /// <param name="options">The options for influencing the encoder</param>
 public PngEncoderCore(MemoryAllocator memoryAllocator, IPngEncoderOptions options)
 {
     this.memoryAllocator  = memoryAllocator;
     this.pngBitDepth      = options.BitDepth;
     this.use16Bit         = this.pngBitDepth.Equals(PngBitDepth.Bit16);
     this.pngColorType     = options.ColorType;
     this.pngFilterMethod  = options.FilterMethod;
     this.compressionLevel = options.CompressionLevel;
     this.gamma            = options.Gamma;
     this.quantizer        = options.Quantizer;
     this.threshold        = options.Threshold;
     this.writeGamma       = options.WriteGamma;
 }
Esempio n. 12
0
        private static void TestPngEncoderCore <TPixel>(
            TestImageProvider <TPixel> provider,
            PngColorType pngColorType,
            int compressionLevel        = 6,
            int paletteSize             = 0,
            bool appendPngColorType     = false,
            bool appendPixelType        = false,
            bool appendCompressionLevel = false,
            bool appendPaletteSize      = false)
            where TPixel : struct, IPixel <TPixel>
        {
            using (Image <TPixel> image = provider.GetImage())
            {
                if (!HasAlpha(pngColorType))
                {
                    image.Mutate(c => c.MakeOpaque());
                }

                var encoder = new PngEncoder
                {
                    PngColorType     = pngColorType,
                    CompressionLevel = compressionLevel,
                    PaletteSize      = paletteSize
                };

                string pngColorTypeInfo     = appendPngColorType ? pngColorType.ToString() : "";
                string compressionLevelInfo = appendCompressionLevel ? $"_C{compressionLevel}" : "";
                string paletteSizeInfo      = appendPaletteSize ? $"_PaletteSize-{paletteSize}" : "";
                string debugInfo            = $"{pngColorTypeInfo}{compressionLevelInfo}{paletteSizeInfo}";
                //string referenceInfo = $"{pngColorTypeInfo}";

                // Does DebugSave & load reference CompareToReferenceInput():
                string actualOutputFile = ((ITestImageProvider)provider).Utility.SaveTestOutputFile(image, "png", encoder, debugInfo, appendPixelType);

                IImageDecoder referenceDecoder    = TestEnvironment.GetReferenceDecoder(actualOutputFile);
                string        referenceOutputFile = ((ITestImageProvider)provider).Utility.GetReferenceOutputFileName("png", debugInfo, appendPixelType);

                using (var actualImage = Image.Load <TPixel>(actualOutputFile, referenceDecoder))
                    using (var referenceImage = Image.Load <TPixel>(referenceOutputFile, referenceDecoder))
                    {
                        ImageComparer comparer = pngColorType == PngColorType.Palette
                                                 ? ImageComparer.Tolerant(ToleranceThresholdForPaletteEncoder)
                                                 : ImageComparer.Exact;

                        comparer.VerifySimilarity(referenceImage, actualImage);
                    }
            }
        }
Esempio n. 13
0
        private static string SavePng <TPixel>(TestImageProvider <TPixel> provider, PngColorType pngColorType)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            using (Image <TPixel> sourceImage = provider.GetImage())
            {
                if (pngColorType != PngColorType.RgbWithAlpha)
                {
                    sourceImage.Mutate(c => c.MakeOpaque());
                }

                var encoder = new PngEncoder {
                    ColorType = pngColorType
                };
                return(provider.Utility.SaveTestOutputFile(sourceImage, "png", encoder));
            }
        }
Esempio n. 14
0
        public virtual string GetColorTypeDescription()
        {
            int?value = _directory.GetInteger(PngDirectory.TagColorType);

            if (value == null)
            {
                return(null);
            }
            PngColorType colorType = PngColorType.FromNumericValue((int)value);

            if (colorType == null)
            {
                return(null);
            }
            return(colorType.GetDescription());
        }
Esempio n. 15
0
        private static bool IsPaletted(byte bitDepth, PngColorType colorType)
        {
            if (bitDepth == 8)
            {
                if (colorType == (PngColorType.Indexed | PngColorType.Color))
                {
                    return(true);
                }
                if (colorType == (PngColorType.Color | PngColorType.Alpha) || colorType == PngColorType.Color)
                {
                    return(false);
                }
            }

            throw new InvalidDataException("Unknown pixel format (" + bitDepth + "-bit, " + colorType + ") specified");
        }
Esempio n. 16
0
 public PngHeader(
     int width,
     int height,
     byte bitDepth,
     PngColorType colorType,
     byte compressionMethod,
     byte filterMethod,
     PngInterlaceMode interlaceMethod)
 {
     this.Width             = width;
     this.Height            = height;
     this.BitDepth          = bitDepth;
     this.ColorType         = colorType;
     this.CompressionMethod = compressionMethod;
     this.FilterMethod      = filterMethod;
     this.InterlaceMethod   = interlaceMethod;
 }
Esempio n. 17
0
        static bool IsPaletted(byte bitDepth, PngColorType colorType)
        {
            if (bitDepth == 8 && colorType == (PngColorType.Indexed | PngColorType.Color))
            {
                return(true);
            }

            if (bitDepth == 8 && colorType == (PngColorType.Color | PngColorType.Alpha))
            {
                return(false);
            }

            if (bitDepth == 8 && colorType == PngColorType.Color)
            {
                return(false);
            }

            throw new InvalidDataException("Unknown pixel format");
        }
Esempio n. 18
0
        /// <summary>
        /// Validates the png header.
        /// </summary>
        /// <exception cref="NotSupportedException">
        /// Thrown if the image does pass validation.
        /// </exception>
        private void ValidateHeader()
        {
            if (!ColorTypes.ContainsKey(this.header.ColorType))
            {
                throw new NotSupportedException("Color type is not supported or not valid.");
            }

            if (!ColorTypes[this.header.ColorType].Contains(this.header.BitDepth))
            {
                throw new NotSupportedException("Bit depth is not supported or not valid.");
            }

            if (this.header.FilterMethod != 0)
            {
                throw new NotSupportedException("The png specification only defines 0 as filter method.");
            }

            if (this.header.InterlaceMethod != PngInterlaceMode.None && this.header.InterlaceMethod != PngInterlaceMode.Adam7)
            {
                throw new NotSupportedException("The png specification only defines 'None' and 'Adam7' as interlaced methods.");
            }

            this.PngColorType = (PngColorType)this.header.ColorType;
        }
Esempio n. 19
0
 public void WorksWithAllBitDepths <TPixel>(TestImageProvider <TPixel> provider, PngColorType pngColorType, PngBitDepth pngBitDepth)
     where TPixel : struct, IPixel <TPixel>
 {
     TestPngEncoderCore(
         provider,
         pngColorType,
         PngFilterMethod.Adaptive,
         pngBitDepth,
         appendPngColorType: true,
         appendPixelType: true,
         appendPngBitDepth: true);
 }
Esempio n. 20
0
        public void EncodeGeneratedPatterns <TPixel>(TestImageProvider <TPixel> provider, PngColorType pngColorType)
            where TPixel : struct, IPixel <TPixel>
        {
            using (Image <TPixel> image = provider.GetImage())
            {
                PngEncoderOptions options = new PngEncoderOptions()
                {
                    PngColorType = pngColorType
                };
                provider.Utility.TestName += "_" + pngColorType;

                provider.Utility.SaveTestOutputFile(image, "png", new PngEncoder(), options);
            }
        }
Esempio n. 21
0
        public void InfersColorTypeAndBitDepth <TPixel>(TestImageProvider <TPixel> provider, PngColorType pngColorType, PngBitDepth pngBitDepth)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            using (Stream stream = new MemoryStream())
            {
                PngEncoder.Encode(provider.GetImage(), stream);

                stream.Seek(0, SeekOrigin.Begin);

                var decoder = new PngDecoder();

                Image image = decoder.Decode(Configuration.Default, stream);

                PngMetadata metadata = image.Metadata.GetPngMetadata();
                Assert.Equal(pngColorType, metadata.ColorType);
                Assert.Equal(pngBitDepth, metadata.BitDepth);
            }
        }
Esempio n. 22
0
 public void WorksWithAllBitDepthsAndExcludeAllFilter <TPixel>(TestImageProvider <TPixel> provider, PngColorType pngColorType, PngBitDepth pngBitDepth)
     where TPixel : unmanaged, IPixel <TPixel>
 {
     foreach (var filterMethod in PngFilterMethods)
     {
         foreach (PngInterlaceMode interlaceMode in InterlaceMode)
         {
             TestPngEncoderCore(
                 provider,
                 pngColorType,
                 (PngFilterMethod)filterMethod[0],
                 pngBitDepth,
                 interlaceMode,
                 appendPngColorType: true,
                 appendPixelType: true,
                 appendPngBitDepth: true,
                 optimizeMethod: PngChunkFilter.ExcludeAll);
         }
     }
 }
Esempio n. 23
0
        public void WorksWithAllBitDepths <TPixel>(TestImageProvider <TPixel> provider, PngColorType pngColorType, PngBitDepth pngBitDepth)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            // TODO: Investigate WuQuantizer to see if we can reduce memory pressure.
            if (TestEnvironment.RunsOnCI && !TestEnvironment.Is64BitProcess)
            {
                return;
            }

            foreach (var filterMethod in PngFilterMethods)
            {
                foreach (PngInterlaceMode interlaceMode in InterlaceMode)
                {
                    TestPngEncoderCore(
                        provider,
                        pngColorType,
                        (PngFilterMethod)filterMethod[0],
                        pngBitDepth,
                        interlaceMode,
                        appendPngColorType: true,
                        appendPixelType: true,
                        appendPngBitDepth: true);
                }
            }
        }
Esempio n. 24
0
 public void IsNotBoundToSinglePixelType <TPixel>(TestImageProvider <TPixel> provider, PngColorType pngColorType)
     where TPixel : unmanaged, IPixel <TPixel>
 {
     foreach (PngInterlaceMode interlaceMode in InterlaceMode)
     {
         TestPngEncoderCore(
             provider,
             pngColorType,
             PngFilterMethod.Adaptive,
             PngBitDepth.Bit8,
             interlaceMode,
             appendPixelType: true,
             appendPngColorType: true);
     }
 }
Esempio n. 25
0
 public void WorksWithDifferentSizes <TPixel>(TestImageProvider <TPixel> provider, PngColorType pngColorType)
     where TPixel : unmanaged, IPixel <TPixel>
 {
     TestPngEncoderCore(
         provider,
         pngColorType,
         PngFilterMethod.Adaptive,
         PngBitDepth.Bit8,
         PngInterlaceMode.None,
         appendPngColorType: true);
 }
Esempio n. 26
0
        static PixelFormat MakePixelFormat(byte bitDepth, PngColorType colorType)
        {
            if (bitDepth == 8 && colorType == (PngColorType.Indexed | PngColorType.Color))
                return PixelFormat.Format8bppIndexed;

            throw new InvalidDataException("Unknown pixelformat");
        }
Esempio n. 27
0
        /// <summary>
        /// Encodes the image to the specified stream from the <see cref="Image{TColor}"/>.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <param name="image">The <see cref="ImageBase{TColor}"/> to encode from.</param>
        /// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
        public void Encode <TColor>(Image <TColor> image, Stream stream)
            where TColor : struct, IPixel <TColor>
        {
            Guard.NotNull(image, nameof(image));
            Guard.NotNull(stream, nameof(stream));

            this.width  = image.Width;
            this.height = image.Height;

            // Write the png header.
            this.chunkDataBuffer[0] = 0x89; // Set the high bit.
            this.chunkDataBuffer[1] = 0x50; // P
            this.chunkDataBuffer[2] = 0x4E; // N
            this.chunkDataBuffer[3] = 0x47; // G
            this.chunkDataBuffer[4] = 0x0D; // Line ending CRLF
            this.chunkDataBuffer[5] = 0x0A; // Line ending CRLF
            this.chunkDataBuffer[6] = 0x1A; // EOF
            this.chunkDataBuffer[7] = 0x0A; // LF

            stream.Write(this.chunkDataBuffer, 0, 8);

            // Ensure that quality can be set but has a fallback.
            this.quality = this.options.Quality > 0 ? this.options.Quality : image.MetaData.Quality;
            this.quality = this.quality > 0 ? this.quality.Clamp(1, int.MaxValue) : int.MaxValue;

            this.pngColorType = this.options.PngColorType;
            this.quantizer    = this.options.Quantizer;

            // Set correct color type if the color count is 256 or less.
            if (this.quality <= 256)
            {
                this.pngColorType = PngColorType.Palette;
            }

            if (this.pngColorType == PngColorType.Palette && this.quality > 256)
            {
                this.quality = 256;
            }

            // Set correct bit depth.
            this.bitDepth = this.quality <= 256
                               ? (byte)ImageMaths.GetBitsNeededForColorDepth(this.quality).Clamp(1, 8)
                               : (byte)8;

            // Png only supports in four pixel depths: 1, 2, 4, and 8 bits when using the PLTE chunk
            if (this.bitDepth == 3)
            {
                this.bitDepth = 4;
            }
            else if (this.bitDepth >= 5 || this.bitDepth <= 7)
            {
                this.bitDepth = 8;
            }

            this.bytesPerPixel = this.CalculateBytesPerPixel();

            PngHeader header = new PngHeader
            {
                Width             = image.Width,
                Height            = image.Height,
                ColorType         = (byte)this.pngColorType,
                BitDepth          = this.bitDepth,
                FilterMethod      = 0, // None
                CompressionMethod = 0,
                InterlaceMethod   = 0
            };

            this.WriteHeaderChunk(stream, header);

            // Collect the indexed pixel data
            if (this.pngColorType == PngColorType.Palette)
            {
                this.CollectIndexedBytes(image, stream, header);
            }

            this.WritePhysicalChunk(stream, image);
            this.WriteGammaChunk(stream);
            using (PixelAccessor <TColor> pixels = image.Lock())
            {
                this.WriteDataChunks(pixels, stream);
            }

            this.WriteEndChunk(stream);
            stream.Flush();
        }
Esempio n. 28
0
 private static bool HasAlpha(PngColorType pngColorType) =>
 pngColorType == PngColorType.GrayscaleWithAlpha || pngColorType == PngColorType.RgbWithAlpha;
Esempio n. 29
0
 public void IsNotBoundToSinglePixelType <TPixel>(TestImageProvider <TPixel> provider, PngColorType pngColorType)
     where TPixel : struct, IPixel <TPixel>
 {
     TestPngEncoderCore(provider, pngColorType, appendPixelType: true, appendPngColorType: true);
 }
Esempio n. 30
0
 public void WorksWithDifferentSizes <TPixel>(TestImageProvider <TPixel> provider, PngColorType pngColorType)
     where TPixel : struct, IPixel <TPixel>
 {
     TestPngEncoderCore(provider, pngColorType, appendPngColorType: true);
 }
Esempio n. 31
0
 public void IsNotBoundToSinglePixelType <TPixel>(TestImageProvider <TPixel> provider, PngColorType pngColorType)
     where TPixel : struct, IPixel <TPixel>
 {
     TestPngEncoderCore(
         provider,
         pngColorType,
         PngFilterMethod.Adaptive,
         PngBitDepth.Bit8,
         appendPixelType: true,
         appendPngColorType: true);
 }