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
}
- [MonoTODO]
public PropertyItem GetPropertyItem(int propid)
{
- throw new NotImplementedException ();
+ 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 Image GetThumbnailImage(int thumbWidth, int thumbHeight, Image.GetThumbnailImageAbort callback, IntPtr callbackData)
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);
+ GDIPlus.CheckStatus (st);
}
public void SaveAdd (Image image, EncoderParameters encoderParams)
IntPtr nativeEncoderParams = encoderParams.ToNativePtr ();
st = GDIPlus.GdipSaveAddImage (nativeObject, image.NativeObject, nativeEncoderParams);
Marshal.FreeHGlobal (nativeEncoderParams);
+ GDIPlus.CheckStatus (st);
}
public int SelectActiveFrame(FrameDimension dimension, int frameIndex)
return frameIndex;
}
- [MonoTODO]
public void SetPropertyItem(PropertyItem propitem)
{
- throw new NotImplementedException ();
+ IntPtr property;
+ int size = Marshal.SizeOf (typeof(GdipPropertyItem));
+ property = Marshal.AllocHGlobal (size);
+
+ Marshal.StructureToPtr (propitem, property, true);
+ Status status = GDIPlus.GdipSetPropertyItem (nativeObject, property);
+ GDIPlus.CheckStatus (status);
}
// properties
[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 {
[Browsable (false)]
public int[] PropertyIdList {
get {
- PropertyItem [] propItems = this.PropertyItems ;
- int length = propItems.Length;
- int [] ids = new int [length];
- for (int i = 0; i < length; i++)
- ids [i] = propItems [i].Id;
-
- return ids;
+ 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 {
- int prop_ptr, prop_size;
- uint bufferSize, numProperties;
-
- Status st = GDIPlus.GdipGetPropertySize (nativeObject,
- out bufferSize, out numProperties);
- GDIPlus.CheckStatus (st);
-
- IntPtr dest = Marshal.AllocHGlobal ( (int)bufferSize);
+ 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);
- st = GDIPlus.GdipGetAllPropertyItems (nativeObject, bufferSize,
- numProperties, out dest);
- GDIPlus.CheckStatus (st);
+ 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);
- GdipPropertyItem gdipProp = new GdipPropertyItem();
- PropertyItem [] propItems = new PropertyItem [numProperties] ;
- prop_size = Marshal.SizeOf (gdipProp);
- prop_ptr = dest.ToInt32();
+ propSize = Marshal.SizeOf (gdipProperty);
+ propPtr = properties;
- for (int i = 0; i < numProperties; i++, prop_ptr += prop_size) {
- gdipProp = (GdipPropertyItem) Marshal.PtrToStructure
- ((IntPtr)prop_ptr, typeof (GdipPropertyItem));
- GdipPropertyItem.MarshalTo (gdipProp, propItems [i]);
+ 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 (dest);
- return propItems;
+ Marshal.FreeHGlobal (properties);
+ return items;
}
}
public void Dispose ()
{
Dispose (true);
+ System.GC.SuppressFinalize (this);
}
~Image ()
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)
{
- if (nativeObject != (IntPtr) 0){
+ if (nativeObject != IntPtr.Zero){
DisposeResources ();
- nativeObject=IntPtr.Zero;
+ nativeObject = IntPtr.Zero;
}
}
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)
- return new Bitmap (newimage);
-
+
+ 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 ();
}
}