Silverlight导出图片需要的几个类

来源:互联网 发布:北京行知实验小学 编辑:程序博客网 时间:2024/05/18 00:49

1、EditableImage.cs类,代码如下:

using System;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Ink;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;using System.IO;namespace MapClient.CommonClass{    public class EditableImage    {        private int _width = 0;        private int _height = 0;        private bool _init = false;        private byte[] _buffer;        private int _rowLength;        public event EventHandler<EditableImageErrorEventArgs> ImageError;        public EditableImage(int width, int height)        {            this.Width = width;            this.Height = height;        }        public int Width        {            get            {                return _width;            }            set            {                if (_init)                {                    OnImageError("Error: Cannot change Width after the EditableImage has been initialized");                }                else if ((value <= 0) || (value > 2047))                {                    OnImageError("Error: Width must be between 0 and 2047");                }                else                {                    _width = value;                }            }        }        public int Height        {            get            {                return _height;            }            set            {                if (_init)                {                    OnImageError("Error: Cannot change Height after the EditableImage has been initialized");                }                else if ((value <= 0) || (value > 2047))                {                    OnImageError("Error: Height must be between 0 and 2047");                }                else                {                    _height = value;                }            }        }        public void SetPixel(int col, int row, Color color)        {            SetPixel(col, row, color.R, color.G, color.B, color.A);        }        public void SetPixel(int col, int row, byte red, byte green, byte blue, byte alpha)        {            if (!_init)            {                _rowLength = _width * 4 + 1;                _buffer = new byte[_rowLength * _height];                // Initialize                for (int idx = 0; idx < _height; idx++)                {                    _buffer[idx * _rowLength] = 0;      // Filter bit                }                _init = true;            }            if ((col > _width) || (col < 0))            {                OnImageError("Error: Column must be greater than 0 and less than the Width");            }            else if ((row > _height) || (row < 0))            {                OnImageError("Error: Row must be greater than 0 and less than the Height");            }            // Set the pixel            int start = _rowLength * row + col * 4 + 1;            _buffer[start] = red;            _buffer[start + 1] = green;            _buffer[start + 2] = blue;            _buffer[start + 3] = alpha;        }        public Color GetPixel(int col, int row)        {            if ((col > _width) || (col < 0))            {                OnImageError("Error: Column must be greater than 0 and less than the Width");            }            else if ((row > _height) || (row < 0))            {                OnImageError("Error: Row must be greater than 0 and less than the Height");            }            Color color = new Color();            int _base = _rowLength * row + col + 1;            color.R = _buffer[_base];            color.G = _buffer[_base + 1];            color.B = _buffer[_base + 2];            color.A = _buffer[_base + 3];            return color;        }        public Stream GetStream()        {            Stream stream;            if (!_init)            {                OnImageError("Error: Image has not been initialized");                stream = null;            }            else            {                stream = PngEncoder.Encode(_buffer, _width, _height);            }            return stream;        }        private void OnImageError(string msg)        {            if (null != ImageError)            {                EditableImageErrorEventArgs args = new EditableImageErrorEventArgs();                args.ErrorMessage = msg;                ImageError(this, args);            }        }        public class EditableImageErrorEventArgs : EventArgs        {            private string _errorMessage = string.Empty;            public string ErrorMessage            {                get { return _errorMessage; }                set { _errorMessage = value; }            }        }    }}


2、ElementToPNG.cs类,代码如下:

using System;using System.Net;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Ink;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;using System.Windows.Media.Imaging;using System.IO;namespace MapClient.CommonClass{    /// <summary>    /// Based on:    ///     /// Andy Beaulieu    /// http://www.andybeaulieu.com/Home/tabid/67/EntryID/161/Default.aspx    ///     ///     /// Tom Giam    /// http://silverlight.net/forums/t/108713.aspx    /// </summary>    public class ElementToPNG    {        public void ShowSaveDialog(UIElement elementToExport)        {            //Canvas canvasToExport = e as Canvas;            // Instantiate SaveFileDialog            // and set defautl settings (just PNG export)            SaveFileDialog sfd = new SaveFileDialog()            {                DefaultExt = "png",                Filter = "Png files (*.png)|*.png|All files (*.*)|*.*",                FilterIndex = 1            };            if (sfd.ShowDialog() == true)            {                SaveAsPNG(sfd, elementToExport);            }        }        private void SaveAsPNG(SaveFileDialog sfd, UIElement elementToExport)        {            WriteableBitmap bitmap = new WriteableBitmap(elementToExport, new TranslateTransform());            EditableImage imageData = new EditableImage(bitmap.PixelWidth, bitmap.PixelHeight);            try            {                for (int y = 0; y < bitmap.PixelHeight; ++y)                {                    for (int x = 0; x < bitmap.PixelWidth; ++x)                    {                        int pixel = bitmap.Pixels[bitmap.PixelWidth * y + x];                        imageData.SetPixel(x, y,                        (byte)((pixel >> 16) & 0xFF),                        (byte)((pixel >> 8) & 0xFF),                        (byte)(pixel & 0xFF), (byte)((pixel >> 24) & 0xFF)                        );                    }                }            }            catch (System.Security.SecurityException)            {                throw new Exception("Cannot print images from other domains");            }            // Save it to disk            Stream pngStream = imageData.GetStream();            //StreamReader sr = new StreamReader(pngStream);            byte[] binaryData = new Byte[pngStream.Length];            long bytesRead = pngStream.Read(binaryData, 0, (int)pngStream.Length);            //using (Stream stream = sfd.OpenFile())            //{            //    stream.Write(binaryData, 0, binaryData.Length);            //    stream.Close();            //}            Stream stream = sfd.OpenFile();            stream.Write(binaryData, 0, binaryData.Length);            stream.Close();        }    }}


3、PngEncoder.cs类,代码如下:
using System;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Ink;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;using System.IO;using System.Windows.Browser;using System.Reflection;namespace MapClient.CommonClass{    public class PngEncoder    {        private const int _ADLER32_BASE = 65521;        private const int _MAXBLOCK = 0xFFFF;        private static byte[] _HEADER = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };        private static byte[] _IHDR = { (byte)'I', (byte)'H', (byte)'D', (byte)'R' };        private static byte[] _GAMA = { (byte)'g', (byte)'A', (byte)'M', (byte)'A' };        private static byte[] _IDAT = { (byte)'I', (byte)'D', (byte)'A', (byte)'T' };        private static byte[] _IEND = { (byte)'I', (byte)'E', (byte)'N', (byte)'D' };        private static byte[] _4BYTEDATA = { 0, 0, 0, 0 };        private static byte[] _ARGB = { 0, 0, 0, 0, 0, 0, 0, 0, 8, 6, 0, 0, 0 };        public static Stream Encode(byte[] data, int width, int height)        {            MemoryStream ms = new MemoryStream();            byte[] size;            // Write PNG header            ms.Write(_HEADER, 0, _HEADER.Length);            // Write IHDR            //  Width:              4 bytes            //  Height:             4 bytes            //  Bit depth:          1 byte            //  Color type:         1 byte            //  Compression method: 1 byte            //  Filter method:      1 byte            //  Interlace method:   1 byte            size = BitConverter.GetBytes(width);            _ARGB[0] = size[3]; _ARGB[1] = size[2]; _ARGB[2] = size[1]; _ARGB[3] = size[0];            size = BitConverter.GetBytes(height);            _ARGB[4] = size[3]; _ARGB[5] = size[2]; _ARGB[6] = size[1]; _ARGB[7] = size[0];            // Write IHDR chunk            WriteChunk(ms, _IHDR, _ARGB);            // Set gamma = 1            size = BitConverter.GetBytes(1 * 100000);            _4BYTEDATA[0] = size[3]; _4BYTEDATA[1] = size[2]; _4BYTEDATA[2] = size[1]; _4BYTEDATA[3] = size[0];            // Write gAMA chunk            WriteChunk(ms, _GAMA, _4BYTEDATA);            // Write IDAT chunk            uint widthLength = (uint)(width * 4) + 1;            uint dcSize = widthLength * (uint)height;            // First part of ZLIB header is 78 1101 1010 (DA) 0000 00001 (01)            // ZLIB info            //            // CMF Byte: 78            //  CINFO = 7 (32K window size)            //  CM = 8 = (deflate compression)            // FLG Byte: DA            //  FLEVEL = 3 (bits 6 and 7 - ignored but signifies max compression)            //  FDICT = 0 (bit 5, 0 - no preset dictionary)            //  FCHCK = 26 (bits 0-4 - ensure CMF*256+FLG / 31 has no remainder)            // Compressed data            //  FLAGS: 0 or 1            //    00000 00 (no compression) X (X=1 for last block, 0=not the last block)            //    LEN = length in bytes (equal to ((width*4)+1)*height            //    NLEN = one's compliment of LEN            //    Example: 1111 1011 1111 1111 (FB), 0000 0100 0000 0000 (40)            //    Data for each line: 0 [RGBA] [RGBA] [RGBA] ...            //    ADLER32            uint adler = ComputeAdler32(data);            MemoryStream comp = new MemoryStream();            // Calculate number of 64K blocks            uint rowsPerBlock = _MAXBLOCK / widthLength;            uint blockSize = rowsPerBlock * widthLength;            uint blockCount;            ushort length;            uint remainder = dcSize;            if ((dcSize % blockSize) == 0)            {                blockCount = dcSize / blockSize;            }            else            {                blockCount = (dcSize / blockSize) + 1;            }            // Write headers            comp.WriteByte(0x78);            comp.WriteByte(0xDA);            for (uint blocks = 0; blocks < blockCount; blocks++)            {                // Write LEN                length = (ushort)((remainder < blockSize) ? remainder : blockSize);                if (length == remainder)                {                    comp.WriteByte(0x01);                }                else                {                    comp.WriteByte(0x00);                }                comp.Write(BitConverter.GetBytes(length), 0, 2);                // Write one's compliment of LEN                comp.Write(BitConverter.GetBytes((ushort)~length), 0, 2);                // Write blocks                comp.Write(data, (int)(blocks * blockSize), length);                // Next block                remainder -= blockSize;            }            WriteReversedBuffer(comp, BitConverter.GetBytes(adler));            comp.Seek(0, SeekOrigin.Begin);            byte[] dat = new byte[comp.Length];            comp.Read(dat, 0, (int)comp.Length);            WriteChunk(ms, _IDAT, dat);            // Write IEND chunk            WriteChunk(ms, _IEND, new byte[0]);            // Reset stream            ms.Seek(0, SeekOrigin.Begin);            return ms;            // See http://www.libpng.org/pub/png//spec/1.2/PNG-Chunks.html            // See http://www.libpng.org/pub/png/book/chapter08.html#png.ch08.div.4            // See http://www.gzip.org/zlib/rfc-zlib.html (ZLIB format)            // See ftp://ftp.uu.net/pub/archiving/zip/doc/rfc1951.txt (ZLIB compression format)        }        private static void WriteReversedBuffer(Stream stream, byte[] data)        {            int size = data.Length;            byte[] reorder = new byte[size];            for (int idx = 0; idx < size; idx++)            {                reorder[idx] = data[size - idx - 1];            }            stream.Write(reorder, 0, size);        }        private static void WriteChunk(Stream stream, byte[] type, byte[] data)        {            int idx;            int size = type.Length;            byte[] buffer = new byte[type.Length + data.Length];            // Initialize buffer            for (idx = 0; idx < type.Length; idx++)            {                buffer[idx] = type[idx];            }            for (idx = 0; idx < data.Length; idx++)            {                buffer[idx + size] = data[idx];            }            // Write length            WriteReversedBuffer(stream, BitConverter.GetBytes(data.Length));            // Write type and data            stream.Write(buffer, 0, buffer.Length);   // Should always be 4 bytes            // Compute and write the CRC            WriteReversedBuffer(stream, BitConverter.GetBytes(GetCRC(buffer)));        }        private static uint[] _crcTable = new uint[256];        private static bool _crcTableComputed = false;        private static void MakeCRCTable()        {            uint c;            for (int n = 0; n < 256; n++)            {                c = (uint)n;                for (int k = 0; k < 8; k++)                {                    if ((c & (0x00000001)) > 0)                        c = 0xEDB88320 ^ (c >> 1);                    else                        c = c >> 1;                }                _crcTable[n] = c;            }            _crcTableComputed = true;        }        private static uint UpdateCRC(uint crc, byte[] buf, int len)        {            uint c = crc;            if (!_crcTableComputed)            {                MakeCRCTable();            }            for (int n = 0; n < len; n++)            {                c = _crcTable[(c ^ buf[n]) & 0xFF] ^ (c >> 8);            }            return c;        }        /* Return the CRC of the bytes buf[0..len-1]. */        private static uint GetCRC(byte[] buf)        {            return UpdateCRC(0xFFFFFFFF, buf, buf.Length) ^ 0xFFFFFFFF;        }        private static uint ComputeAdler32(byte[] buf)        {            uint s1 = 1;            uint s2 = 0;            int length = buf.Length;            for (int idx = 0; idx < length; idx++)            {                s1 = (s1 + (uint)buf[idx]) % _ADLER32_BASE;                s2 = (s2 + s1) % _ADLER32_BASE;            }            return (s2 << 16) + s1;        }    }}

===========================================================================

如果觉得对您有帮助,微信扫一扫支持一下:


2 0