2006-08-07 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / System.Drawing / System.Drawing / Image.cs
index 97dbbed863b60368556b37ced1b852f2275981cf..a2371aa8159395eaee69506ada4912ab9dfcec83 100644 (file)
@@ -53,6 +53,7 @@ namespace System.Drawing
 public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISerializable 
 {
        public delegate bool GetThumbnailImageAbort();
+       private object tag;
        
        internal IntPtr nativeObject = IntPtr.Zero;     
        
@@ -85,7 +86,7 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
                MemoryStream ms = new MemoryStream ();
-               this.Save (ms, ImageFormat.Bmp);
+               this.Save (ms, RawFormat);
                info.AddValue ("Data", ms.ToArray ());
        }
     
@@ -139,6 +140,12 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer
                return new Bitmap (stream, useECM);
        }
 
+       // See http://support.microsoft.com/default.aspx?scid=kb;en-us;831419 for performance discussion        
+       public static Image FromStream (Stream stream, bool useECM, bool validateImageData)
+       {
+               return new Bitmap (stream, useECM);
+       }
+
        public static int GetPixelFormatSize(PixelFormat pixfmt)
        {
                int result = 0;
@@ -285,13 +292,11 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer
                        status = GDIPlus.GdipGetEncoderParameterList (nativeObject, ref format, sz, rawEPList);
                        eps = EncoderParameters.FromNativePtr (rawEPList);
                        GDIPlus.CheckStatus (status);
-               } catch {
+               }
+               finally {
                        Marshal.FreeHGlobal (rawEPList);
-                       throw;
                }
 
-               Marshal.FreeHGlobal (rawEPList);
-
                return eps;
        }
        
@@ -321,34 +326,36 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer
 
                /* Get PropertyItem */
                property = Marshal.AllocHGlobal (propSize);
-               status = GDIPlus.GdipGetPropertyItem (nativeObject, propid, propSize,  
-                                                                               property);
-               GDIPlus.CheckStatus (status);
-               gdipProperty = (GdipPropertyItem) Marshal.PtrToStructure ((IntPtr)property, 
+               try {
+                       status = GDIPlus.GdipGetPropertyItem (nativeObject, propid, propSize, property);
+                       GDIPlus.CheckStatus (status);
+                       gdipProperty = (GdipPropertyItem) Marshal.PtrToStructure (property, 
                                                                typeof (GdipPropertyItem));                                             
-               GdipPropertyItem.MarshalTo (gdipProperty, item);                                                                
-               
-               Marshal.FreeHGlobal (property);
+                       GdipPropertyItem.MarshalTo (gdipProperty, item);
+               }
+               finally {
+                       Marshal.FreeHGlobal (property);
+               }
                return item;
        }
        
-       public Image GetThumbnailImage(int thumbWidth, int thumbHeight, Image.GetThumbnailImageAbort callback, IntPtr callbackData)
+       public Image GetThumbnailImage (int thumbWidth, int thumbHeight, Image.GetThumbnailImageAbort callback, IntPtr callbackData)
        {
-               Status          status;
-               Image           ThumbNail;
-               Graphics        g;
+               if ((thumbWidth <= 0) || (thumbHeight <= 0))
+                       throw new OutOfMemoryException ("Invalid thumbnail size");
 
-               ThumbNail=new Bitmap(thumbWidth, thumbHeight);
-               g=Graphics.FromImage(ThumbNail);
-               
-               status = GDIPlus.GdipDrawImageRectRectI(g.nativeObject, nativeObject,
-                                       0, 0, thumbWidth, thumbHeight,
-                                       0, 0, this.Width, this.Height,
-                                       GraphicsUnit.Pixel, IntPtr.Zero, null, IntPtr.Zero);
-                GDIPlus.CheckStatus (status);
-               g.Dispose();
+               Image ThumbNail = new Bitmap (thumbWidth, thumbHeight);
+
+               using (Graphics g = Graphics.FromImage (ThumbNail)) {
+                       Status status = GDIPlus.GdipDrawImageRectRectI (g.nativeObject, nativeObject,
+                               0, 0, thumbWidth, thumbHeight,
+                               0, 0, this.Width, this.Height,
+                               GraphicsUnit.Pixel, IntPtr.Zero, null, IntPtr.Zero);
+
+                       GDIPlus.CheckStatus (status);
+               }
 
-               return(ThumbNail);
+               return ThumbNail;
        }
        
        
@@ -494,6 +501,8 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer
                Marshal.StructureToPtr (propitem, property, true);
                Status status = GDIPlus.GdipSetPropertyItem (nativeObject, property);
                GDIPlus.CheckStatus (status);
+               // FIXME: GdipSetPropertyItem isn't implemented in libgdiplus (but returns Ok)
+               // so who's freeing "property" ? GDI+ ?
        }
 
        // properties   
@@ -657,23 +666,24 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer
                                        
                        /* Get PropertyItem list*/
                        properties = Marshal.AllocHGlobal (propsSize * propNums);
-                       
-                       status = GDIPlus.GdipGetAllPropertyItems (nativeObject, propsSize, 
+                       try {
+                               status = GDIPlus.GdipGetAllPropertyItems (nativeObject, propsSize, 
                                                                propNums, properties);
-                       GDIPlus.CheckStatus (status);
+                               GDIPlus.CheckStatus (status);
 
-                       propSize = Marshal.SizeOf (gdipProperty);                       
-                       propPtr = properties;
+                               propSize = Marshal.SizeOf (gdipProperty);                       
+                               propPtr = properties;
                        
-                       for (int i = 0; i < propNums; i++, propPtr = new IntPtr (propPtr.ToInt64 () + propSize))
-                       {
-                               gdipProperty = (GdipPropertyItem) Marshal.PtrToStructure 
+                               for (int i = 0; i < propNums; i++, propPtr = new IntPtr (propPtr.ToInt64 () + propSize)) {
+                                       gdipProperty = (GdipPropertyItem) Marshal.PtrToStructure 
                                                (propPtr, typeof (GdipPropertyItem));                                           
-                               items [i] = new PropertyItem ();
-                               GdipPropertyItem.MarshalTo (gdipProperty, items [i]);                                                           
+                                       items [i] = new PropertyItem ();
+                                       GdipPropertyItem.MarshalTo (gdipProperty, items [i]);                                                           
+                               }
+                       }
+                       finally {
+                               Marshal.FreeHGlobal (properties);
                        }
-                       
-                       Marshal.FreeHGlobal (properties);
                        return items;
                }
        }
@@ -693,7 +703,17 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer
                        return new Size(Width, Height);
                }
        }
-       
+
+#if NET_2_0
+       [DefaultValue (null)]
+       [LocalizableAttribute(false)] 
+       [BindableAttribute(true)]       
+       [TypeConverter (typeof (StringConverter))]
+       public object Tag { 
+               get { return tag; }
+               set { tag = value; }
+       }
+#endif 
        public float VerticalResolution {
                get {
                        float resolution;
@@ -738,38 +758,28 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer
                Dispose (false);
        }
 
-       private void DisposeResources ()
-       {
-               Status status = GDIPlus.GdipDisposeImage (nativeObject);
-               GDIPlus.CheckStatus (status);           
-       }
-       
        protected virtual void Dispose (bool disposing)
        {
                if (nativeObject != IntPtr.Zero){
-                       DisposeResources ();
+                       Status status = GDIPlus.GdipDisposeImage (nativeObject);
+                       // set nativeObject to null before throwing an exception
                        nativeObject = IntPtr.Zero;
+                       GDIPlus.CheckStatus (status);           
                }
        }
        
-       public virtual object Clone()
-       {                               
+       public object Clone ()
+       {
+               Bitmap b = (this as Bitmap);
+               if (b == null)
+                       throw new NotImplementedException ("This Image instance isn't a Bitmap instance."); 
 
                IntPtr newimage = IntPtr.Zero;
-               
-               if (!(this is Bitmap)) 
-                       throw new NotImplementedException (); 
-               
                Status status = GDIPlus.GdipCloneImage (NativeObject, out newimage);                    
                GDIPlus.CheckStatus (status);                   
 
-               if (this is Bitmap){
-                       return new Bitmap (newimage);
-               }
-               
-               throw new NotImplementedException ();           
+               return new Bitmap (newimage);
        }
-
 }
 
 }