using System.ComponentModel;
using System.Drawing.Imaging;
using System.IO;
+using System.Reflection;
namespace System.Drawing
{
public delegate bool GetThumbnailImageAbort();
internal IntPtr nativeObject = IntPtr.Zero;
- ColorPalette colorPalette;
// constructor
internal Image()
- {
- colorPalette = new ColorPalette();
+ {
+
}
private Image (SerializationInfo info, StreamingContext context)
}
}
}
+
+ private static bool IsIndexedPixelFormat(PixelFormat pixfmt)
+ {
+ return ((pixfmt & PixelFormat.Indexed) != 0);
+ }
+
- [MonoTODO]
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
- throw new NotImplementedException();
+ MemoryStream ms = new MemoryStream ();
+ this.Save (ms, ImageFormat.Bmp);
+ info.AddValue ("Data", ms.ToArray ());
}
// public methods
// static
public static Image FromFile(string filename)
{
- return new Bitmap (filename);
+ return FromFile (filename, false);
}
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);
}
- [MonoTODO]
public static Bitmap FromHbitmap(IntPtr hbitmap)
- {
- throw new NotImplementedException ();
+ {
+ return FromHbitmap (hbitmap, IntPtr.Zero);
}
- [MonoTODO]
public static Bitmap FromHbitmap(IntPtr hbitmap, IntPtr hpalette)
{
- throw new NotImplementedException ();
+ IntPtr imagePtr;
+ Status st;
+
+ st = GDIPlus.GdipCreateBitmapFromHBITMAP (hbitmap, hpalette, out imagePtr);
+
+ GDIPlus.CheckStatus (st);
+ return new Bitmap (imagePtr);
}
public static Image FromStream (Stream stream)
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
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)
IntPtr nativeEncoderParams = encoderParams.ToNativePtr ();
st = GDIPlus.GdipSaveAdd (nativeObject, nativeEncoderParams);
- Marshal.FreeHGlobal (nativeEncoderParams);\r
+ Marshal.FreeHGlobal (nativeEncoderParams);
GDIPlus.CheckStatus (st);
}
IntPtr nativeEncoderParams = encoderParams.ToNativePtr ();
st = GDIPlus.GdipSaveAddImage (nativeObject, image.NativeObject, nativeEncoderParams);
- Marshal.FreeHGlobal (nativeEncoderParams);\r
+ Marshal.FreeHGlobal (nativeEncoderParams);
GDIPlus.CheckStatus (st);
}
[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 {
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)
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 ();
}
}