2005-10-04 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / System.Drawing / System.Drawing / Image.cs
index 09671d3cd67990b79098b84f18344082a093eea0..83edd59dcfa76697df0ceb623c27775a8ef1eed1 100644 (file)
 //
 // System.Drawing.Image.cs
 //
-// (C) 2002 Ximian, Inc.  http://www.ximian.com
-// Author: Christian Meyer
-// eMail: Christian.Meyer@cs.tum.edu
+// Copyright (C) 2002 Ximian, Inc.  http://www.ximian.com
+// Copyright (C) 2004 Novell, Inc.  http://www.novell.com
 //
-// Many methods are still commented. I'll care about them when all necessary
-// classes are implemented.
+// Author:     Christian Meyer (Christian.Meyer@cs.tum.edu)
+//             Alexandre Pigolkine (pigolkine@gmx.de)
+//             Jordi Mas i Hernandez (jordi@ximian.com)
+//             Sanjay Gupta (gsanjay@novell.com)
+//             Ravindra (rkumar@novell.com)
+//
+
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
 // 
-// Alexandre Pigolkine (pigolkine@gmx.de)
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
 // 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-namespace System.Drawing {
 
 using System;
 using System.Runtime.Remoting;
 using System.Runtime.Serialization;
+using System.Runtime.InteropServices;
+using System.ComponentModel;
 using System.Drawing.Imaging;
 using System.IO;
+using System.Reflection;
 
-internal class InternalImageInfo {
-       Size         image_size;
-       PixelFormat  format;
-       int          stride;
-       ColorPalette palette;
-       byte[]       image;
-       ImageFormat  rawFormat;
-
-       internal InternalImageInfo()
-       {
-               palette = new ColorPalette();
-               image_size = new Size(0,0);
-               format = PixelFormat.Format32bppArgb;
-               image = new byte[0];
-               stride = 0;
-       }
-
-       internal Size Size {
-               get { return image_size; }
-               set { image_size = value; }
-       }
-
-       internal PixelFormat Format {
-               get { return format; }
-               set { format = value; }
-       }
-
-       internal ColorPalette Palette {
-               get { return palette; }
-               set { palette = value; }
-       }
-
-       internal byte[] RawImageBytes {
-               get { return image; }
-               set { image = value; }
-       }
-
-       internal int Stride {
-               get { return stride; }
-               set { stride = value; }
-       }
-
-       internal ImageFormat RawFormat {
-               get { return rawFormat; }
-               set { rawFormat = value; }
+namespace System.Drawing
+{
+[Serializable]
+[ComVisible (true)]
+[Editor ("System.Drawing.Design.ImageEditor, " + Consts.AssemblySystem_Drawing_Design, typeof (System.Drawing.Design.UITypeEditor))]
+[TypeConverter (typeof(ImageConverter))]
+[ImmutableObject (true)]
+public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISerializable 
+{
+       public delegate bool GetThumbnailImageAbort();
+       
+       internal IntPtr nativeObject = IntPtr.Zero;     
+       
+       
+       // constructor
+       internal  Image()
+       {       
+               
        }
        
-       public override string ToString()
+       private Image (SerializationInfo info, StreamingContext context)
        {
-               return String.Format("InternalImageInfo. Size {0}, PixelFormat {1}, Stride {2}, Image size {3}",
-                       image_size, format, stride, image.Length);
-       }
-}
-
-[Serializable]
-//[ComVisible(true)]
-public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISerializable {
+               foreach (SerializationEntry serEnum in info) {
+                       if (String.Compare(serEnum.Name, "Data", true) == 0) {
+                               byte[] bytes = (byte[]) serEnum.Value;
 
-       internal IImage implementation = null;
-       protected Size image_size;
-       
-       // constructor
-       public Image () {}
+                               if (bytes != null) {
+                                       InitFromStream(new MemoryStream(bytes));
+                               }
+                       }
+               }
+       }
 
-               private Image (SerializationInfo info, StreamingContext context)
+       private static bool IsIndexedPixelFormat(PixelFormat pixfmt)
        {
+               return ((pixfmt & PixelFormat.Indexed) != 0);
        }
 
+       
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
+               MemoryStream ms = new MemoryStream ();
+               this.Save (ms, ImageFormat.Bmp);
+               info.AddValue ("Data", ms.ToArray ());
        }
     
        // public methods
        // static
-       public static Image FromFile (string filename)
+       public static Image FromFile(string filename)
        {
-               return new Bitmap (filename);
+               return FromFile (filename, false);
        }
        
-       public static Image FromFile (string filename, bool useEmbeddedColorManagement)
+       public static Image FromFile(string filename, bool useEmbeddedColorManagement)
        {
-               return new Bitmap (filename, useEmbeddedColorManagement);
+               IntPtr imagePtr;
+               Status st;
+
+               if (!File.Exists (filename))
+                       throw new FileNotFoundException (filename);
+
+               if (useEmbeddedColorManagement)
+                       st = GDIPlus.GdipLoadImageFromFileICM (filename, out imagePtr);
+               else
+                       st = GDIPlus.GdipLoadImageFromFile (filename, out imagePtr);
+
+               GDIPlus.CheckStatus (st);
+               return new Bitmap (imagePtr);
        }
-       
-       public static Bitmap FromHbitmap (IntPtr hbitmap)
+
+       public static Bitmap FromHbitmap(IntPtr hbitmap)
        {
-               // Fixme: implement me
-               throw new NotImplementedException ();
+               return FromHbitmap (hbitmap, IntPtr.Zero);
        }
 
-       public static Bitmap FromHbitmap (IntPtr hbitmap, IntPtr hpalette)
-       {
-               // Fixme: implement me
-               throw new NotImplementedException ();
+       public static Bitmap FromHbitmap(IntPtr hbitmap, IntPtr hpalette)
+       {               
+               IntPtr imagePtr;
+               Status st;
+
+               st = GDIPlus.GdipCreateBitmapFromHBITMAP (hbitmap, hpalette, out imagePtr);
+
+               GDIPlus.CheckStatus (st);
+               return new Bitmap (imagePtr);
        }
 
-       internal static InternalImageInfo Decode( Stream streamIn) {
-               Stream stream = streamIn;
-               InternalImageInfo       result = new InternalImageInfo();
-               if (!stream.CanSeek) {
-                       // FIXME: if stream.CanSeek == false, copy to a MemoryStream and read nicely 
-               }
-               ImageCodecInfo[] availableDecoders = ImageCodecInfo.GetImageDecoders();
-               long pos = stream.Position;
-               ImageCodecInfo codecToUse = null;
-               foreach( ImageCodecInfo info in availableDecoders) {
-                       for (int i = 0; i < info.SignaturePatterns.Length; i++) {
-                               stream.Seek(pos, SeekOrigin.Begin);
-                               bool codecFound = true;
-                               for (int iPattern = 0; iPattern < info.SignaturePatterns[i].Length; iPattern++) {
-                                       byte pattern = (byte)stream.ReadByte();
-                                       pattern &= info.SignatureMasks[i][iPattern];
-                                       if( pattern != info.SignaturePatterns[i][iPattern]) {
-                                               codecFound = false;
-                                               break;
-                                       }
-                               }
-                               if (codecFound) {
-                                       codecToUse = info;
-                                       break;
-                               }
-                       }
-               }
-               stream.Seek (pos, SeekOrigin.Begin);
-               if (codecToUse != null && codecToUse.decode != null) {
-                       codecToUse.decode( stream, result);
-               }
-               return result;
+       public static Image FromStream (Stream stream)
+       {
+               return new Bitmap (stream);
        }
        
-       public static int GetPixelFormatSize (PixelFormat pixfmt)
+       public static Image FromStream (Stream stream, bool useECM)
+       {
+               return new Bitmap (stream, useECM);
+       }
+
+       public static int GetPixelFormatSize(PixelFormat pixfmt)
        {
                int result = 0;
                switch (pixfmt) {
@@ -187,7 +177,7 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer
                return result;
        }
 
-       public static bool IsAlphaPixelFormat (PixelFormat pixfmt)
+       public static bool IsAlphaPixelFormat(PixelFormat pixfmt)
        {
                bool result = false;
                switch (pixfmt) {
@@ -213,177 +203,570 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer
                return result;
        }
        
-//     public static bool IsCanonicalPixelFormat (PixelFormat pixfmt)
-//     {
-//             // Fixme: implement me
-//             throw new NotImplementedException ();
-//     }
-//     
-//     public static bool IsExtendedPixelFormat (PixelFormat pixfmt)
-//     {
-//             // Fixme: implement me
-//             throw new NotImplementedException ();
-//     }
-
-       // non-static
+       public static bool IsCanonicalPixelFormat (PixelFormat pixfmt)
+       {
+               return ((pixfmt & PixelFormat.Canonical) != 0);
+       }
+       
+       public static bool IsExtendedPixelFormat (PixelFormat pixfmt)
+       {
+               return ((pixfmt & PixelFormat.Extended) != 0);
+       }
+
+       internal void InitFromStream (Stream stream)
+       {
+               IntPtr imagePtr;
+               Status st;
+               
+               // Seeking required
+               if (!stream.CanSeek) {
+                       byte[] buffer = new byte[256];
+                       int index = 0;
+                       int count;
+
+                       do {
+                               if (buffer.Length < index + 256) {
+                                       byte[] newBuffer = new byte[buffer.Length * 2];
+                                       Array.Copy(buffer, newBuffer, buffer.Length);
+                                       buffer = newBuffer;
+                               }
+                               count = stream.Read(buffer, index, 256);
+                               index += count;
+                       }
+                       while (count != 0);
+
+                       stream = new MemoryStream(buffer, 0, index);
+               }
+
+               // check for Unix platforms - see FAQ for more details
+               // http://www.mono-project.com/FAQ:_Technical#How_to_detect_the_execution_platform_.3F
+               int platform = (int) Environment.OSVersion.Platform;
+               if ((platform == 4) || (platform == 128)) {
+                       // Unix, with libgdiplus
+                       // We use a custom API for this, because there's no easy way
+                       // to get the Stream down to libgdiplus.  So, we wrap the stream
+                       // with a set of delegates.
+                       GDIPlus.GdiPlusStreamHelper sh = new GDIPlus.GdiPlusStreamHelper (stream);
+
+                       st = GDIPlus.GdipLoadImageFromDelegate_linux (sh.GetHeaderDelegate, sh.GetBytesDelegate,
+                               sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, out imagePtr);
+               } else {
+                       // this is MS-land
+                       st = GDIPlus.GdipLoadImageFromStream(new ComIStreamWrapper(stream), out imagePtr);
+               }
+
+               GDIPlus.CheckStatus (st);
+               nativeObject = imagePtr;
+       }
+
+       // non-static   
        public RectangleF GetBounds (ref GraphicsUnit pageUnit)
+       {       
+               RectangleF source;                      
+               
+               Status status = GDIPlus.GdipGetImageBounds (nativeObject, out source, ref pageUnit);
+               GDIPlus.CheckStatus (status);           
+               
+               return source;
+       }
+       
+       public EncoderParameters GetEncoderParameterList(Guid format)
+       {
+               Status status;
+               uint sz;
+
+               status = GDIPlus.GdipGetEncoderParameterListSize (nativeObject, ref format, out sz);
+               GDIPlus.CheckStatus (status);
+
+               IntPtr rawEPList = Marshal.AllocHGlobal ((int) sz);
+               EncoderParameters eps;
+
+               try {
+                       status = GDIPlus.GdipGetEncoderParameterList (nativeObject, ref format, sz, rawEPList);
+                       eps = EncoderParameters.FromNativePtr (rawEPList);
+                       GDIPlus.CheckStatus (status);
+               } catch {
+                       Marshal.FreeHGlobal (rawEPList);
+                       throw;
+               }
+
+               Marshal.FreeHGlobal (rawEPList);
+
+               return eps;
+       }
+       
+       public int GetFrameCount(FrameDimension dimension)
        {
-               // Fixme: implement me
-               throw new NotImplementedException ();
+               int count;
+               Guid guid = dimension.Guid;
+               Status status = GDIPlus.GdipImageGetFrameCount (nativeObject, ref guid, out  count); 
+
+               GDIPlus.CheckStatus (status);           
+               
+               return count;
+               
        }
        
-       //public EncoderParameters GetEncoderParameterList(Guid encoder);
-       //public int GetFrameCount(FrameDimension dimension);
-       //public PropertyItem GetPropertyItem(int propid);
-       /*
-         public Image GetThumbnailImage(int thumbWidth, int thumbHeight,
-         Image.GetThumbnailImageAbort callback,
-         IntPtr callbackData);
-       */
+       public PropertyItem GetPropertyItem(int propid)
+       {
+               int propSize;
+               IntPtr property;
+               PropertyItem item = new PropertyItem ();
+               GdipPropertyItem gdipProperty = new GdipPropertyItem ();
+               Status status;
+                       
+               status = GDIPlus.GdipGetPropertyItemSize (nativeObject, propid, 
+                                                                       out propSize);
+               GDIPlus.CheckStatus (status);
+
+               /* Get PropertyItem */
+               property = Marshal.AllocHGlobal (propSize);
+               status = GDIPlus.GdipGetPropertyItem (nativeObject, propid, propSize,  
+                                                                               property);
+               GDIPlus.CheckStatus (status);
+               gdipProperty = (GdipPropertyItem) Marshal.PtrToStructure ((IntPtr)property, 
+                                                               typeof (GdipPropertyItem));                                             
+               GdipPropertyItem.MarshalTo (gdipProperty, item);                                                                
+               
+               Marshal.FreeHGlobal (property);
+               return item;
+       }
        
-       public void RemovePropertyItem (int propid)
+       public Image GetThumbnailImage(int thumbWidth, int thumbHeight, Image.GetThumbnailImageAbort callback, IntPtr callbackData)
        {
-               // Fixme: implement me
-               throw new NotImplementedException ();
+               Status          status;
+               Image           ThumbNail;
+               Graphics        g;
+
+               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();
+
+               return(ThumbNail);
        }
        
+       
+       public void RemovePropertyItem (int propid)
+       {               
+               Status status = GDIPlus.GdipRemovePropertyItem (nativeObject, propid);
+               GDIPlus.CheckStatus (status);                                   
+       }       
+       
        public void RotateFlip (RotateFlipType rotateFlipType)
+       {                       
+               Status status = GDIPlus.GdipImageRotateFlip (nativeObject, rotateFlipType);
+               GDIPlus.CheckStatus (status);                           
+       }
+
+       internal ImageCodecInfo findEncoderForFormat (ImageFormat format)
        {
-               // Fixme: implement me
-               throw new NotImplementedException ();
+               ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();                  
+               ImageCodecInfo encoder = null;
+               
+               if (format.Guid.Equals (ImageFormat.MemoryBmp.Guid))
+                       format = ImageFormat.Bmp;
+       
+               /* Look for the right encoder for our format*/
+               for (int i = 0; i < encoders.Length; i++) {
+                       if (encoders[i].FormatID.Equals (format.Guid)) {
+                               encoder = encoders[i];
+                               break;
+                       }                       
+               }
+
+               return encoder;
        }
 
        public void Save (string filename)
        {
-               Savefilename, RawFormat);
+               Save (filename, RawFormat);
        }
 
-       internal virtual InternalImageInfo ConvertToInternalImageInfo() {
-               return implementation.ConvertToInternalImageInfo();
+       public void Save(string filename, ImageFormat format) 
+       {
+               ImageCodecInfo encoder = findEncoderForFormat (format);
+
+               if (encoder == null)
+                       throw new ArgumentException ("No codec available for format:" + format.Guid);
+
+               Save (filename, encoder, null);
        }
 
-       public void Save (Stream stream, ImageFormat format)
+       public void Save(string filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
        {
-               ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
-               foreach (ImageCodecInfo encoder in encoders) {
-                       if (encoder.FormatID == format.Guid) {
-                               if(encoder.encode != null) {
-                                       InternalImageInfo imageInfo = ConvertToInternalImageInfo();
-                                       encoder.encode(stream, imageInfo);
-                               }
-                               break;
-                       }
+               Status st;
+               Guid guid = encoder.Clsid;
+
+               if (encoderParams == null) {
+                       st = GDIPlus.GdipSaveImageToFile (nativeObject, filename, ref guid, IntPtr.Zero);
+               } else {
+                       IntPtr nativeEncoderParams = encoderParams.ToNativePtr ();
+                       st = GDIPlus.GdipSaveImageToFile (nativeObject, filename, ref guid, nativeEncoderParams);
+                       Marshal.FreeHGlobal (nativeEncoderParams);
                }
+
+               GDIPlus.CheckStatus (st);
        }
 
-       public void Save(string filename, ImageFormat format) {
-               FileStream fs = new FileStream( filename, FileMode.Create);
-               Save(fs, format);
-               fs.Flush();
-               fs.Close();
+       public void Save (Stream stream, ImageFormat format)
+       {
+               ImageCodecInfo encoder = findEncoderForFormat (format);
+
+               if (encoder == null)
+                       throw new ArgumentException ("No codec available for format:" + format.Guid);
+
+               Save (stream, encoder, null);
        }
 
-       //public void Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams);
-       //public void Save(string filename, ImageCodecInfo encoder, EncoderParameters encoderParams);
-       //public void SaveAdd(EncoderParameters_ encoderParams);
-       //public void SaveAdd(Image image, EncoderParameters_ encoderParams);
-       //public int SelectActiveFrame(FrameDimension dimension, int frameIndex);
-       //public void SetPropertyItem(PropertyItem propitem);
+       public void Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams)
+       {
+               Status st;
+               IntPtr nativeEncoderParams;
+               Guid guid = encoder.Clsid;
+
+               if (encoderParams == null)
+                       nativeEncoderParams = IntPtr.Zero;
+               else
+                       nativeEncoderParams = encoderParams.ToNativePtr ();
+
+               try {
+                       // check for Unix platforms - see FAQ for more details
+                       // http://www.mono-project.com/FAQ:_Technical#How_to_detect_the_execution_platform_.3F
+                       int platform = (int) Environment.OSVersion.Platform;
+                       if ((platform == 4) || (platform == 128)) {
+                               GDIPlus.GdiPlusStreamHelper sh = new GDIPlus.GdiPlusStreamHelper (stream);
+                               st = GDIPlus.GdipSaveImageToDelegate_linux (nativeObject, sh.GetBytesDelegate, sh.PutBytesDelegate,
+                                       sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, ref guid, nativeEncoderParams);
+                       }
+                       else
+                               st = GDIPlus.GdipSaveImageToStream(new HandleRef(this, nativeObject), new ComIStreamWrapper(stream), ref guid, new HandleRef(encoderParams, nativeEncoderParams));
+               }
+               finally {
+                       if (nativeEncoderParams != IntPtr.Zero)
+                               Marshal.FreeHGlobal (nativeEncoderParams);
+               }
+               
+               GDIPlus.CheckStatus (st);               
+       }
+       
+       public void SaveAdd (EncoderParameters encoderParams)
+       {
+               Status st;
+               
+               IntPtr nativeEncoderParams = encoderParams.ToNativePtr ();
+               st = GDIPlus.GdipSaveAdd (nativeObject, nativeEncoderParams);
+               Marshal.FreeHGlobal (nativeEncoderParams);
+               GDIPlus.CheckStatus (st);
+       }
+               
+       public void SaveAdd (Image image, EncoderParameters encoderParams)
+       {
+               Status st;
+               
+               IntPtr nativeEncoderParams = encoderParams.ToNativePtr ();
+               st = GDIPlus.GdipSaveAddImage (nativeObject, image.NativeObject, nativeEncoderParams);
+               Marshal.FreeHGlobal (nativeEncoderParams);
+               GDIPlus.CheckStatus (st);
+       }
+               
+       public int SelectActiveFrame(FrameDimension dimension, int frameIndex)
+       {
+               Guid guid = dimension.Guid;             
+               Status st = GDIPlus.GdipImageSelectActiveFrame (nativeObject, ref guid, frameIndex);
+               
+               GDIPlus.CheckStatus (st);                       
+               
+               return frameIndex;              
+       }
+       
+       public void SetPropertyItem(PropertyItem propitem)
+       {
+               IntPtr property;
+               int size = Marshal.SizeOf (typeof(GdipPropertyItem));
+               property = Marshal.AllocHGlobal (size);
 
-       // destructor
-       ~Image() {}
+               Marshal.StructureToPtr (propitem, property, true);
+               Status status = GDIPlus.GdipSetPropertyItem (nativeObject, property);
+               GDIPlus.CheckStatus (status);
+       }
 
-       // properties
+       // properties   
+       [Browsable (false)]
        public int Flags {
                get {
-                       throw new NotImplementedException ();
+                       int flags;
+                       
+                       Status status = GDIPlus.GdipGetImageFlags (nativeObject, out flags);                    
+                       GDIPlus.CheckStatus (status);                                           
+                       return flags;                   
                }
        }
        
+       [Browsable (false)]
        public Guid[] FrameDimensionsList {
                get {
-                       throw new NotImplementedException ();
+                       uint found;
+                       Status status = GDIPlus.GdipImageGetFrameDimensionsCount (nativeObject, out found);
+                       GDIPlus.CheckStatus (status);
+                       Guid [] guid = new Guid [found];
+                       status = GDIPlus.GdipImageGetFrameDimensionsList (nativeObject, guid, found);
+                       GDIPlus.CheckStatus (status);  
+                       return guid;
                }
        }
-       
+
+       [DefaultValue (false)]
+       [Browsable (false)]
+       [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
        public int Height {
                get {
-                       return image_size.Height;
+                       int height;                     
+                       Status status = GDIPlus.GdipGetImageHeight (nativeObject, out height);          
+                       GDIPlus.CheckStatus (status);                   
+                       
+                       return height;
                }
        }
        
        public float HorizontalResolution {
                get {
-                       throw new NotImplementedException ();
+                       float resolution;
+                       
+                       Status status = GDIPlus.GdipGetImageHorizontalResolution (nativeObject, out resolution);                        
+                       GDIPlus.CheckStatus (status);                   
+                       
+                       return resolution;
                }
        }
        
-//     public ColorPalette Palette {
-//             get {
-//                     throw new NotImplementedException ();
-//             }
-//             set {
-//                     throw new NotImplementedException ();
-//             }
-//     }
-       
+       [Browsable (false)]
+       public ColorPalette Palette {
+               get {                                                   
+                       return retrieveGDIPalette();
+               }
+               set {
+                       storeGDIPalette(value);
+               }
+       }
+
+       internal ColorPalette retrieveGDIPalette()
+       {
+               ColorPalette ret = new ColorPalette();
+               if (!IsIndexedPixelFormat (PixelFormat)) {
+                       return ret;
+               }
+               Status st;
+               int bytes;
+
+               st = GDIPlus.GdipGetImagePaletteSize (nativeObject, out bytes);
+               GDIPlus.CheckStatus (st);
+               IntPtr palette_data = Marshal.AllocHGlobal (bytes);
+               try {
+                       st = GDIPlus.GdipGetImagePalette (nativeObject, palette_data, bytes);
+                       GDIPlus.CheckStatus (st);
+                       ret.setFromGDIPalette (palette_data);
+                       return ret;
+               }
+
+               finally {
+                       Marshal.FreeHGlobal (palette_data);
+               }
+       }
+
+       internal void storeGDIPalette(ColorPalette palette)
+       {
+               if (palette == null) {
+                       throw new ArgumentNullException("palette");
+               }
+               IntPtr palette_data = palette.getGDIPalette();
+               if (palette_data == IntPtr.Zero) {
+                       return;
+               }
+
+               try {
+                       Status st = GDIPlus.GdipSetImagePalette (nativeObject, palette_data);
+                       GDIPlus.CheckStatus (st);
+               }
+
+               finally {
+                       Marshal.FreeHGlobal(palette_data);
+               }
+       }
+
+               
        public SizeF PhysicalDimension {
                get {
-                       throw new NotImplementedException ();
+                       float width,  height;
+                       Status status = GDIPlus.GdipGetImageDimension (nativeObject, out width, out height);            
+                       GDIPlus.CheckStatus (status);                   
+                       
+                       return new SizeF (width, height);
                }
        }
        
        public PixelFormat PixelFormat {
-               get {
-                       return implementation.PixelFormat;
-               }
+               get {                   
+                       PixelFormat pixFormat;                          
+                       Status status = GDIPlus.GdipGetImagePixelFormat (nativeObject, out pixFormat);          
+                       GDIPlus.CheckStatus (status);                   
+                       
+                       return pixFormat;
+               }               
        }
        
+       [Browsable (false)]
        public int[] PropertyIdList {
                get {
-                       throw new NotImplementedException ();
+                       uint propNumbers;
+                       
+                       Status status = GDIPlus.GdipGetPropertyCount (nativeObject, 
+                                                                       out propNumbers);                       
+                       GDIPlus.CheckStatus (status);
+                       
+                       int [] idList = new int [propNumbers];
+                       status = GDIPlus.GdipGetPropertyIdList (nativeObject, 
+                                                               propNumbers, idList);
+                       GDIPlus.CheckStatus (status);
+                       
+                       return idList;
                }
        }
        
+       [Browsable (false)]
        public PropertyItem[] PropertyItems {
                get {
-                       return implementation.PropertyItems;
+                       int propNums, propsSize, propSize;
+                       IntPtr properties, propPtr;
+                       PropertyItem[] items;
+                       GdipPropertyItem gdipProperty = new GdipPropertyItem ();
+                       Status status;
+                       
+                       status = GDIPlus.GdipGetPropertySize (nativeObject, out propsSize, out propNums);
+                       GDIPlus.CheckStatus (status);
+
+                       items =  new PropertyItem [propNums];
+                       
+                       if (propNums == 0)
+                               return items;                   
+                                       
+                       /* Get PropertyItem list*/
+                       properties = Marshal.AllocHGlobal (propsSize);
+                       status = GDIPlus.GdipGetAllPropertyItems (nativeObject, propsSize, 
+                                                               propNums, properties);
+                       GDIPlus.CheckStatus (status);
+
+                       propSize = Marshal.SizeOf (gdipProperty);                       
+                       propPtr = properties;
+                       
+                       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]);                                                           
+                       }
+                       
+                       Marshal.FreeHGlobal (properties);
+                       return items;
                }
        }
 
        public ImageFormat RawFormat {
                get {
-                       return implementation.RawFormat;
+                       Guid guid;
+                       Status st = GDIPlus.GdipGetImageRawFormat (nativeObject, out guid);
+                       
+                       GDIPlus.CheckStatus (st);
+                       return new ImageFormat (guid);                  
                }
        }
-
+       
        public Size Size {
                get {
-                       return image_size;
+                       return new Size(Width, Height);
                }
        }
        
        public float VerticalResolution {
                get {
-                       throw new NotImplementedException ();
+                       float resolution;
+                       
+                       Status status = GDIPlus.GdipGetImageVerticalResolution (nativeObject, out resolution);
+                       GDIPlus.CheckStatus (status);
+
+                       return resolution;
                }
        }
-       
+
+       [DefaultValue (false)]
+       [Browsable (false)]
+       [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
        public int Width {
                get {
-                       return image_size.Width;
+                       int width;                      
+                       Status status = GDIPlus.GdipGetImageWidth (nativeObject, out width);            
+                       GDIPlus.CheckStatus (status);                   
+                       
+                       return width;
                }
        }
-       [MonoTODO]
+       
+       internal IntPtr NativeObject{
+               get{
+                       return nativeObject;
+               }
+               set     {
+                       nativeObject = value;
+               }
+       }
+       
        public void Dispose ()
        {
-               implementation.Dispose();
+               Dispose (true);
+               System.GC.SuppressFinalize (this);
+       }
+
+       ~Image ()
+       {
+               Dispose (false);
        }
 
-       [MonoTODO]
-       object ICloneable.Clone()
+       private void DisposeResources ()
+       {
+               Status status = GDIPlus.GdipDisposeImage (nativeObject);
+               GDIPlus.CheckStatus (status);           
+       }
+       
+       protected virtual void Dispose (bool disposing)
        {
-               throw new NotImplementedException ();
+               if (nativeObject != IntPtr.Zero){
+                       DisposeResources ();
+                       nativeObject = IntPtr.Zero;
+               }
+       }
+       
+       public virtual object Clone()
+       {                               
+
+               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 ();           
        }
 
 }