private static void WriteGamma(Stream outputStream, WriteableBitmapSavePngParameters parameters)
        {
            if (parameters.SaveGamma)
            {
                var gammaValue = (int)(parameters.Gamma * 100000f);

                var chunkData = CreateChunk(gammaValue);

                WriteChunk(outputStream, PngChunkTypeGamma, chunkData);
            }
        }
        private static void WritePhysics(Stream outputStream, WriteableBitmapSavePngParameters parameters)
        {
            if (parameters.SaveResolution)
            {
                var dpmX = (int)Math.Round(parameters.HorizontalResolution * MetreToInch);
                var dpmY = (int)Math.Round(parameters.VerticalResolution * MetreToInch);

                var chunkData = CreateChunk(dpmX, dpmY, (byte)1);

                WriteChunk(outputStream, PngChunkTypePhysical, chunkData);
            }
        }
        /// <summary>
        /// Encodes a WriteableBitmap object into a PNG stream, using the specified output <see cref="WriteableBitmapSavePngParameters"/>.
        /// </summary>
        /// <param name="writeableBitmap">The writeable bitmap.</param>
        /// <param name="outputStream">The image data stream.</param>
        /// <param name="parameters">The image save parameters.</param>
        public static void SavePng(this WriteableBitmap writeableBitmap, Stream outputStream, WriteableBitmapSavePngParameters parameters)
        {
            WriteHeader(outputStream, writeableBitmap);

            WritePhysics(outputStream, parameters);

            WriteGamma(outputStream, parameters);

            WriteDataChunks(outputStream, writeableBitmap, parameters);

            WriteFooter(outputStream);

            outputStream.Flush();
        }
        private static void WritePhysics(Stream outputStream, WriteableBitmapSavePngParameters parameters)
        {
            if (parameters.SaveResolution)
            {
                var dpmX = (int)Math.Round(parameters.HorizontalResolution * MetreToInch);
                var dpmY = (int)Math.Round(parameters.VerticalResolution * MetreToInch);

                var chunkData = CreateChunk(dpmX, dpmY, (byte)1);

                WriteChunk(outputStream, PngChunkTypePhysical, chunkData);
            }
        }
        private static void WriteGamma(Stream outputStream, WriteableBitmapSavePngParameters parameters)
        {
            if (parameters.SaveGamma)
            {
                var gammaValue = (int)(parameters.Gamma * 100000f);

                var chunkData = CreateChunk(gammaValue);

                WriteChunk(outputStream, PngChunkTypeGamma, chunkData);
            }
        }
        private static void WriteDataChunks(Stream outputStream, WriteableBitmap writeableBitmap, WriteableBitmapSavePngParameters parameters)
        {
            using (var chunkedStream = new ChunkedStream(MaximumChunkSize, data => WriteChunk(outputStream, PngChunkTypeData, data)))
            {
                using (var zlibStream = new ZlibStream(chunkedStream, CompressionMode.Compress, parameters.CompressionLevel, true))
                {
                    writeableBitmap.Invalidate();

                    var pixels = writeableBitmap.Pixels;
                    var width = writeableBitmap.PixelWidth;
                    var height = writeableBitmap.PixelHeight;
                    var index = 0;

                    var dataRowLength = width * 4;
                    var dataRow = new byte[dataRowLength];

                    for (var y = 0; y < height; y++)
                    {
                        zlibStream.WriteByte(0);

                        for (var x = 0; x < width; x++)
                        {
                            var color = pixels[index++];

                            var alpha = (byte)(color >> 24);

                            int alphaInt = alpha;

                            if (alphaInt == 0)
                            {
                                alphaInt = 1;
                            }

                            alphaInt = (255 << 8) / alphaInt;

                            var dataRowOffset = x * 4;

                            dataRow[dataRowOffset] = (byte)((((color >> 16) & 0xFF) * alphaInt) >> 8);
                            dataRow[dataRowOffset + 1] = (byte)((((color >> 8) & 0xFF) * alphaInt) >> 8);
                            dataRow[dataRowOffset + 2] = (byte)(((color & 0xFF) * alphaInt) >> 8);
                            dataRow[dataRowOffset + 3] = alpha;
                        }

                        zlibStream.Write(dataRow, 0, dataRowLength);
                    }
                }
            }
        }
 /// <summary>
 /// Encodes a WriteableBitmap object into a PNG stream, using the specified output <see cref="WriteableBitmapSavePngParameters"/>.
 /// </summary>
 /// <param name="writeableBitmap">The writeable bitmap.</param>
 /// <param name="outputStream">The image data stream.</param>
 /// <param name="parameters">The image save parameters.</param>
 /// <returns>The <see cref="Task"/> object representing the asynchronous operation.</returns>
 public static Task SavePngAsync(this WriteableBitmap writeableBitmap, Stream outputStream, WriteableBitmapSavePngParameters parameters)
 {
     return Task.Factory.StartNew(() =>
     {
         writeableBitmap.SavePng(outputStream, parameters);
     });
 }
        /// <summary>
        /// Encodes a WriteableBitmap object into a PNG stream, using the specified output <see cref="WriteableBitmapSavePngParameters"/>.
        /// </summary>
        /// <param name="writeableBitmap">The writeable bitmap.</param>
        /// <param name="outputStream">The image data stream.</param>
        /// <param name="parameters">The image save parameters.</param>
        public static void SavePng(this WriteableBitmap writeableBitmap, Stream outputStream, WriteableBitmapSavePngParameters parameters)
        {
            WriteHeader(outputStream, writeableBitmap);

            WritePhysics(outputStream, parameters);

            WriteGamma(outputStream, parameters);

            WriteDataChunks(outputStream, writeableBitmap, parameters);

            WriteFooter(outputStream);

            outputStream.Flush();
        }
        private static void WriteDataChunks(Stream outputStream, WriteableBitmap writeableBitmap, WriteableBitmapSavePngParameters parameters)
        {
            using (var chunkedStream = new ChunkedStream(MaximumChunkSize, data => WriteChunk(outputStream, PngChunkTypeData, data)))
            {
                using (var zlibStream = new ZlibStream(chunkedStream, CompressionMode.Compress, parameters.CompressionLevel, true))
                {
                    var pixels = writeableBitmap.Pixels;
                    var width  = writeableBitmap.PixelWidth;
                    var height = writeableBitmap.PixelHeight;
                    var index  = 0;

                    var dataRowLength = width * 4;
                    var dataRow       = new byte[dataRowLength];

                    for (var y = 0; y < height; y++)
                    {
                        zlibStream.WriteByte(0);

                        for (var x = 0; x < width; x++)
                        {
                            var color = pixels[index++];

                            var alpha = (byte)(color >> 24);

                            int alphaInt = alpha;

                            if (alphaInt == 0)
                            {
                                alphaInt = 1;
                            }

                            alphaInt = (255 << 8) / alphaInt;

                            var dataRowOffset = x * 4;

                            dataRow[dataRowOffset]     = (byte)((((color >> 16) & 0xFF) * alphaInt) >> 8);
                            dataRow[dataRowOffset + 1] = (byte)((((color >> 8) & 0xFF) * alphaInt) >> 8);
                            dataRow[dataRowOffset + 2] = (byte)(((color & 0xFF) * alphaInt) >> 8);
                            dataRow[dataRowOffset + 3] = alpha;
                        }

                        zlibStream.Write(dataRow, 0, dataRowLength);
                    }
                }
            }
        }
 /// <summary>
 /// Encodes a WriteableBitmap object into a PNG stream, using the specified output <see cref="WriteableBitmapSavePngParameters"/>.
 /// </summary>
 /// <param name="writeableBitmap">The writeable bitmap.</param>
 /// <param name="outputStream">The image data stream.</param>
 /// <param name="parameters">The image save parameters.</param>
 /// <returns>The <see cref="Task"/> object representing the asynchronous operation.</returns>
 public static Task SavePngAsync(this WriteableBitmap writeableBitmap, Stream outputStream, WriteableBitmapSavePngParameters parameters)
 {
     return(Task.Factory.StartNew(() =>
     {
         writeableBitmap.SavePng(outputStream, parameters);
     }));
 }