X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Drawing%2FSystem.Drawing%2FImage.cs;h=54432fc76dbfa0d1e917df1dc699001ce66c332f;hb=91dc0ba72e27518015d49c55f91a8cce3acf4bfa;hp=335e89d6df8d293317714b15af579e50317683dd;hpb=ace997c3928ddd63a2103ba3787f869785d2a709;p=mono.git diff --git a/mcs/class/System.Drawing/System.Drawing/Image.cs b/mcs/class/System.Drawing/System.Drawing/Image.cs index 335e89d6df8..54432fc76db 100644 --- a/mcs/class/System.Drawing/System.Drawing/Image.cs +++ b/mcs/class/System.Drawing/System.Drawing/Image.cs @@ -41,6 +41,7 @@ using System.Runtime.InteropServices; using System.ComponentModel; using System.Drawing.Imaging; using System.IO; +using System.Reflection; namespace System.Drawing { @@ -54,13 +55,12 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer public delegate bool GetThumbnailImageAbort(); internal IntPtr nativeObject = IntPtr.Zero; - ColorPalette colorPalette; // constructor internal Image() - { - colorPalette = new ColorPalette(); + { + } private Image (SerializationInfo info, StreamingContext context) @@ -75,6 +75,12 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer } } } + + private static bool IsIndexedPixelFormat(PixelFormat pixfmt) + { + return ((pixfmt & PixelFormat.Indexed) != 0); + } + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { @@ -193,28 +199,48 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer internal void InitFromStream (Stream stream) { - if (Environment.OSVersion.Platform == (PlatformID) 128) { + 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); - IntPtr imagePtr; - Status st = GDIPlus.GdipLoadImageFromDelegate_linux (sh.GetBytesDelegate, sh.PutBytesDelegate, - sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, - out imagePtr); - GDIPlus.CheckStatus (st); - nativeObject = imagePtr; + st = GDIPlus.GdipLoadImageFromDelegate_linux (sh.GetHeaderDelegate, sh.GetBytesDelegate, + sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, out imagePtr); } else { // this is MS-land - // FIXME - // We can't call the native gdip functions here, because they expect - // a COM IStream interface. So, a hack is to create a tmp file, read - // the stream, and then load from the tmp file. - // This is an ugly hack. - throw new NotImplementedException ("Bitmap.InitFromStream (win32)"); + st = GDIPlus.GdipLoadImageFromStream(new ComIStreamWrapper(stream), out imagePtr); } + + GDIPlus.CheckStatus (st); + nativeObject = imagePtr; } // non-static @@ -385,23 +411,32 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer public void Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams) { Status st; + IntPtr nativeEncoderParams; Guid guid = encoder.Clsid; - if (Environment.OSVersion.Platform == (PlatformID) 128) { - GDIPlus.GdiPlusStreamHelper sh = new GDIPlus.GdiPlusStreamHelper (stream); - if (encoderParams == null) { - st = GDIPlus.GdipSaveImageToDelegate_linux (nativeObject, sh.GetBytesDelegate, sh.PutBytesDelegate, - sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, ref guid, IntPtr.Zero); - } else { - IntPtr nativeEncoderParams = encoderParams.ToNativePtr (); + 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); - Marshal.FreeHGlobal (nativeEncoderParams); + sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, ref guid, nativeEncoderParams); } - } else { - throw new NotImplementedException ("Image.Save(Stream) (win32)"); + else + st = GDIPlus.GdipSaveImageToStream(new HandleRef(this, nativeObject), new ComIStreamWrapper(stream), ref guid, new HandleRef(encoderParams, nativeEncoderParams)); } - GDIPlus.CheckStatus (st); + finally { + if (nativeEncoderParams != IntPtr.Zero) + Marshal.FreeHGlobal (nativeEncoderParams); + } + + GDIPlus.CheckStatus (st); } public void SaveAdd (EncoderParameters encoderParams) @@ -410,7 +445,7 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer IntPtr nativeEncoderParams = encoderParams.ToNativePtr (); st = GDIPlus.GdipSaveAdd (nativeObject, nativeEncoderParams); - Marshal.FreeHGlobal (nativeEncoderParams); + Marshal.FreeHGlobal (nativeEncoderParams); GDIPlus.CheckStatus (st); } @@ -420,7 +455,7 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer IntPtr nativeEncoderParams = encoderParams.ToNativePtr (); st = GDIPlus.GdipSaveAddImage (nativeObject, image.NativeObject, nativeEncoderParams); - Marshal.FreeHGlobal (nativeEncoderParams); + Marshal.FreeHGlobal (nativeEncoderParams); GDIPlus.CheckStatus (st); } @@ -497,13 +532,57 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer [Browsable (false)] public ColorPalette Palette { get { - - return colorPalette; + return retrieveGDIPalette(); } set { - colorPalette = value; + 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 { @@ -644,11 +723,8 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer private void DisposeResources () { - lock (this) - { - Status status = GDIPlus.GdipDisposeImage (nativeObject); - GDIPlus.CheckStatus (status); - } + Status status = GDIPlus.GdipDisposeImage (nativeObject); + GDIPlus.CheckStatus (status); } protected virtual void Dispose (bool disposing) @@ -661,27 +737,20 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer public virtual object Clone() { - lock (this) - { - 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){ - Bitmap b = new Bitmap (newimage); - - if (colorPalette != null) - b.colorPalette = colorPalette.Clone (); - - return b; - } - + 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 (); } }