| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 | using System;using System.Drawing;using System.Drawing.Imaging;using System.Globalization;using System.IO;using System.Reflection;using System.Runtime.CompilerServices;using System.Runtime.Serialization.Formatters.Binary;namespace PaintDotNet.SystemLayer{    /// <summary>    /// Re-implements System.Drawing.PropertyItem so that the data is serializable.    /// </summary>    [Serializable]    internal sealed class PropertyItem2    {        private const string piElementName = "exif";        private const string idPropertyName = "id";        private const string lenPropertyName = "len";        private const string typePropertyName = "type";        private const string valuePropertyName = "value";        private int id;        private int len;        private short type;        private byte[] value;        public int Id        {            get            {                return id;            }        }        public int Len        {            get            {                return len;            }        }        public short Type        {            get            {                return type;            }        }        public byte[] Value        {            get            {                return (byte[])value.Clone();            }        }        public PropertyItem2(int id, int len, short type, byte[] value)        {            this.id = id;            this.len = len;            this.type = type;            if (value == null)            {                this.value = new byte[0];            }            else            {                this.value = (byte[])value.Clone();            }            if (len != this.value.Length)            {                Tracing.Ping("len != value.Length: id=" + id + ", type=" + type);            }        }        public string ToBlob()        {            string blob = string.Format("<{0} {1}=\"{2}\" {3}=\"{4}\" {5}=\"{6}\" {7}=\"{8}\" />",                piElementName,                idPropertyName, this.id.ToString(CultureInfo.InvariantCulture),                lenPropertyName, this.len.ToString(CultureInfo.InvariantCulture),                typePropertyName, this.type.ToString(CultureInfo.InvariantCulture),                valuePropertyName, Convert.ToBase64String(this.value));            return blob;        }        [MethodImpl(MethodImplOptions.Synchronized)]        public PropertyItem ToPropertyItem()        {            PropertyItem pi = GetPropertyItem();            pi.Id = this.Id;            pi.Len = this.Len;            pi.Type = this.Type;            pi.Value = this.Value;            return pi;        }        public static PropertyItem2 FromPropertyItem(PropertyItem pi)        {            return new PropertyItem2(pi.Id, pi.Len, pi.Type, pi.Value);        }        private static string GetProperty(string blob, string propertyName)        {            string findMe = propertyName + "=\"";            int startIndex = blob.IndexOf(findMe) + findMe.Length;            int endIndex = blob.IndexOf("\"", startIndex);            string propertyValue = blob.Substring(startIndex, endIndex - startIndex);            return propertyValue;        }        public static PropertyItem2 FromBlob(string blob)        {            PropertyItem2 pi2;            if (blob.Length > 0 && blob[0] == '<')            {                string idStr = GetProperty(blob, idPropertyName);                string lenStr = GetProperty(blob, lenPropertyName);                string typeStr = GetProperty(blob, typePropertyName);                string valueStr = GetProperty(blob, valuePropertyName);                int id = int.Parse(idStr, CultureInfo.InvariantCulture);                int len = int.Parse(lenStr, CultureInfo.InvariantCulture);                short type = short.Parse(typeStr, CultureInfo.InvariantCulture);                byte[] value = Convert.FromBase64String(valueStr);                pi2 = new PropertyItem2(id, len, type, value);            }            else            {                // Old way of serializing: .NET serialized!                byte[] bytes = Convert.FromBase64String(blob);                MemoryStream ms = new MemoryStream(bytes);                BinaryFormatter bf = new BinaryFormatter();                SerializationFallbackBinder sfb = new SerializationFallbackBinder();                sfb.AddAssembly(Assembly.GetExecutingAssembly());                bf.Binder = sfb;                pi2 = (PropertyItem2)bf.Deserialize(ms);            }            return pi2;        }        // System.Drawing.Imaging.PropertyItem does not have a public constructor        // So, as per the documentation, we have to "steal" one.        // Quite ridiculous.        // This depends on PropertyItem.png being an embedded resource in this assembly.        private static Image propertyItemImage;        [MethodImpl(MethodImplOptions.Synchronized)]        private static PropertyItem GetPropertyItem()        {            if (propertyItemImage == null)            {                Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PaintDotNet.SystemLayer.PropertyItem.png");                propertyItemImage = Image.FromStream(stream);            }            PropertyItem pi = propertyItemImage.PropertyItems[0];            pi.Id = 0;            pi.Len = 0;            pi.Type = 0;            pi.Value = new byte[0];            return pi;        }    }}
 |