(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / System.Drawing / System.Drawing / Image.cs
blob46d0379ecbb796534ee979953bc1014a7a2e7fbb
1 //
2 // System.Drawing.Image.cs
3 //
4 // Copyright (C) 2002 Ximian, Inc. http://www.ximian.com
5 // Copyright (C) 2004 Novell, Inc. http://www.novell.com
6 //
7 // Author: Christian Meyer (Christian.Meyer@cs.tum.edu)
8 // Alexandre Pigolkine (pigolkine@gmx.de)
9 // Jordi Mas i Hernandez (jordi@ximian.com)
10 // Sanjay Gupta (gsanjay@novell.com)
11 // Ravindra (rkumar@novell.com)
15 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
17 // Permission is hereby granted, free of charge, to any person obtaining
18 // a copy of this software and associated documentation files (the
19 // "Software"), to deal in the Software without restriction, including
20 // without limitation the rights to use, copy, modify, merge, publish,
21 // distribute, sublicense, and/or sell copies of the Software, and to
22 // permit persons to whom the Software is furnished to do so, subject to
23 // the following conditions:
24 //
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
27 //
28 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 using System;
38 using System.Runtime.Remoting;
39 using System.Runtime.Serialization;
40 using System.Runtime.InteropServices;
41 using System.ComponentModel;
42 using System.Drawing.Imaging;
43 using System.IO;
45 namespace System.Drawing
47 [Serializable]
48 [ComVisible (true)]
49 [Editor ("System.Drawing.Design.ImageEditor, " + Consts.AssemblySystem_Drawing_Design, typeof (System.Drawing.Design.UITypeEditor))]
50 [TypeConverter (typeof(ImageConverter))]
51 [ImmutableObject (true)]
52 public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISerializable
54 public delegate bool GetThumbnailImageAbort();
56 internal IntPtr nativeObject = IntPtr.Zero;
57 ColorPalette colorPalette;
60 // constructor
61 internal Image()
63 colorPalette = new ColorPalette();
66 private Image (SerializationInfo info, StreamingContext context)
68 foreach (SerializationEntry serEnum in info) {
69 if (String.Compare(serEnum.Name, "Data", true) == 0) {
70 byte[] bytes = (byte[]) serEnum.Value;
72 if (bytes != null) {
73 InitFromStream(new MemoryStream(bytes));
79 [MonoTODO]
80 void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
82 throw new NotImplementedException();
85 // public methods
86 // static
87 public static Image FromFile(string filename)
89 return new Bitmap (filename);
92 public static Image FromFile(string filename, bool useEmbeddedColorManagement)
94 return new Bitmap (filename, useEmbeddedColorManagement);
97 [MonoTODO]
98 public static Bitmap FromHbitmap(IntPtr hbitmap)
100 throw new NotImplementedException ();
103 [MonoTODO]
104 public static Bitmap FromHbitmap(IntPtr hbitmap, IntPtr hpalette)
106 throw new NotImplementedException ();
109 public static Image FromStream (Stream stream)
111 return new Bitmap (stream);
114 public static Image FromStream (Stream stream, bool useECM)
116 return new Bitmap (stream, useECM);
119 public static int GetPixelFormatSize(PixelFormat pixfmt)
121 int result = 0;
122 switch (pixfmt) {
123 case PixelFormat.Format16bppArgb1555:
124 case PixelFormat.Format16bppGrayScale:
125 case PixelFormat.Format16bppRgb555:
126 case PixelFormat.Format16bppRgb565:
127 result = 16;
128 break;
129 case PixelFormat.Format1bppIndexed:
130 result = 1;
131 break;
132 case PixelFormat.Format24bppRgb:
133 result = 24;
134 break;
135 case PixelFormat.Format32bppArgb:
136 case PixelFormat.Format32bppPArgb:
137 case PixelFormat.Format32bppRgb:
138 result = 32;
139 break;
140 case PixelFormat.Format48bppRgb:
141 result = 48;
142 break;
143 case PixelFormat.Format4bppIndexed:
144 result = 4;
145 break;
146 case PixelFormat.Format64bppArgb:
147 case PixelFormat.Format64bppPArgb:
148 result = 64;
149 break;
150 case PixelFormat.Format8bppIndexed:
151 result = 8;
152 break;
154 return result;
157 public static bool IsAlphaPixelFormat(PixelFormat pixfmt)
159 bool result = false;
160 switch (pixfmt) {
161 case PixelFormat.Format16bppArgb1555:
162 case PixelFormat.Format32bppArgb:
163 case PixelFormat.Format32bppPArgb:
164 case PixelFormat.Format64bppArgb:
165 case PixelFormat.Format64bppPArgb:
166 result = true;
167 break;
168 case PixelFormat.Format16bppGrayScale:
169 case PixelFormat.Format16bppRgb555:
170 case PixelFormat.Format16bppRgb565:
171 case PixelFormat.Format1bppIndexed:
172 case PixelFormat.Format24bppRgb:
173 case PixelFormat.Format32bppRgb:
174 case PixelFormat.Format48bppRgb:
175 case PixelFormat.Format4bppIndexed:
176 case PixelFormat.Format8bppIndexed:
177 result = false;
178 break;
180 return result;
183 public static bool IsCanonicalPixelFormat (PixelFormat pixfmt)
185 return ((pixfmt & PixelFormat.Canonical) != 0);
188 public static bool IsExtendedPixelFormat (PixelFormat pixfmt)
190 return ((pixfmt & PixelFormat.Extended) != 0);
193 internal void InitFromStream (Stream stream)
195 if (Environment.OSVersion.Platform == (PlatformID) 128) {
196 // Unix, with libgdiplus
197 // We use a custom API for this, because there's no easy way
198 // to get the Stream down to libgdiplus. So, we wrap the stream
199 // with a set of delegates.
200 GDIPlus.GdiPlusStreamHelper sh = new GDIPlus.GdiPlusStreamHelper (stream);
201 IntPtr imagePtr;
203 Status st = GDIPlus.GdipLoadImageFromDelegate_linux (sh.GetBytesDelegate, sh.PutBytesDelegate,
204 sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate,
205 out imagePtr);
206 GDIPlus.CheckStatus (st);
207 nativeObject = imagePtr;
208 } else {
209 // this is MS-land
210 // FIXME
211 // We can't call the native gdip functions here, because they expect
212 // a COM IStream interface. So, a hack is to create a tmp file, read
213 // the stream, and then load from the tmp file.
214 // This is an ugly hack.
215 throw new NotImplementedException ("Bitmap.InitFromStream (win32)");
219 // non-static
220 public RectangleF GetBounds (ref GraphicsUnit pageUnit)
222 RectangleF source;
224 Status status = GDIPlus.GdipGetImageBounds (nativeObject, out source, ref pageUnit);
225 GDIPlus.CheckStatus (status);
227 return source;
230 public EncoderParameters GetEncoderParameterList(Guid format)
232 Status status;
233 uint sz;
235 status = GDIPlus.GdipGetEncoderParameterListSize (nativeObject, ref format, out sz);
236 GDIPlus.CheckStatus (status);
238 IntPtr rawEPList = Marshal.AllocHGlobal ((int) sz);
239 EncoderParameters eps;
241 try {
242 status = GDIPlus.GdipGetEncoderParameterList (nativeObject, ref format, sz, rawEPList);
243 eps = EncoderParameters.FromNativePtr (rawEPList);
244 GDIPlus.CheckStatus (status);
245 } catch {
246 Marshal.FreeHGlobal (rawEPList);
247 throw;
250 Marshal.FreeHGlobal (rawEPList);
252 return eps;
255 public int GetFrameCount(FrameDimension dimension)
257 int count;
258 Guid guid = dimension.Guid;
259 Status status = GDIPlus.GdipImageGetFrameCount (nativeObject, ref guid, out count);
261 GDIPlus.CheckStatus (status);
263 return count;
267 public PropertyItem GetPropertyItem(int propid)
269 int propSize;
270 IntPtr property;
271 PropertyItem item = new PropertyItem ();
272 GdipPropertyItem gdipProperty = new GdipPropertyItem ();
273 Status status;
275 status = GDIPlus.GdipGetPropertyItemSize (nativeObject, propid,
276 out propSize);
277 GDIPlus.CheckStatus (status);
279 /* Get PropertyItem */
280 property = Marshal.AllocHGlobal (propSize);
281 status = GDIPlus.GdipGetPropertyItem (nativeObject, propid, propSize,
282 property);
283 GDIPlus.CheckStatus (status);
284 gdipProperty = (GdipPropertyItem) Marshal.PtrToStructure ((IntPtr)property,
285 typeof (GdipPropertyItem));
286 GdipPropertyItem.MarshalTo (gdipProperty, item);
288 Marshal.FreeHGlobal (property);
289 return item;
292 public Image GetThumbnailImage(int thumbWidth, int thumbHeight, Image.GetThumbnailImageAbort callback, IntPtr callbackData)
294 Status status;
295 Image ThumbNail;
296 Graphics g;
298 ThumbNail=new Bitmap(thumbWidth, thumbHeight);
299 g=Graphics.FromImage(ThumbNail);
301 status = GDIPlus.GdipDrawImageRectRectI(g.nativeObject, nativeObject,
302 0, 0, thumbWidth, thumbHeight,
303 0, 0, this.Width, this.Height,
304 GraphicsUnit.Pixel, IntPtr.Zero, null, IntPtr.Zero);
305 GDIPlus.CheckStatus (status);
306 g.Dispose();
308 return(ThumbNail);
312 public void RemovePropertyItem (int propid)
314 Status status = GDIPlus.GdipRemovePropertyItem (nativeObject, propid);
315 GDIPlus.CheckStatus (status);
318 public void RotateFlip (RotateFlipType rotateFlipType)
320 Status status = GDIPlus.GdipImageRotateFlip (nativeObject, rotateFlipType);
321 GDIPlus.CheckStatus (status);
324 internal ImageCodecInfo findEncoderForFormat (ImageFormat format)
326 ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
327 ImageCodecInfo encoder = null;
329 if (format.Guid.Equals (ImageFormat.MemoryBmp.Guid))
330 format = ImageFormat.Bmp;
332 /* Look for the right encoder for our format*/
333 for (int i = 0; i < encoders.Length; i++) {
334 if (encoders[i].FormatID.Equals (format.Guid)) {
335 encoder = encoders[i];
336 break;
340 return encoder;
343 public void Save (string filename)
345 Save (filename, RawFormat);
348 public void Save(string filename, ImageFormat format)
350 ImageCodecInfo encoder = findEncoderForFormat (format);
352 if (encoder == null)
353 throw new ArgumentException ("No codec available for format:" + format.Guid);
355 Save (filename, encoder, null);
358 public void Save(string filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
360 Status st;
361 Guid guid = encoder.Clsid;
363 if (encoderParams == null) {
364 st = GDIPlus.GdipSaveImageToFile (nativeObject, filename, ref guid, IntPtr.Zero);
365 } else {
366 IntPtr nativeEncoderParams = encoderParams.ToNativePtr ();
367 st = GDIPlus.GdipSaveImageToFile (nativeObject, filename, ref guid, nativeEncoderParams);
368 Marshal.FreeHGlobal (nativeEncoderParams);
371 GDIPlus.CheckStatus (st);
374 public void Save (Stream stream, ImageFormat format)
376 ImageCodecInfo encoder = findEncoderForFormat (format);
378 if (encoder == null)
379 throw new ArgumentException ("No codec available for format:" + format.Guid);
381 Save (stream, encoder, null);
384 public void Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams)
386 Status st;
387 Guid guid = encoder.Clsid;
389 if (Environment.OSVersion.Platform == (PlatformID) 128) {
390 GDIPlus.GdiPlusStreamHelper sh = new GDIPlus.GdiPlusStreamHelper (stream);
391 if (encoderParams == null) {
392 st = GDIPlus.GdipSaveImageToDelegate_linux (nativeObject, sh.GetBytesDelegate, sh.PutBytesDelegate,
393 sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, ref guid, IntPtr.Zero);
394 } else {
395 IntPtr nativeEncoderParams = encoderParams.ToNativePtr ();
396 st = GDIPlus.GdipSaveImageToDelegate_linux (nativeObject, sh.GetBytesDelegate, sh.PutBytesDelegate,
397 sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, ref guid, nativeEncoderParams);
398 Marshal.FreeHGlobal (nativeEncoderParams);
400 } else {
401 throw new NotImplementedException ("Image.Save(Stream) (win32)");
403 GDIPlus.CheckStatus (st);
406 public void SaveAdd (EncoderParameters encoderParams)
408 Status st;
410 IntPtr nativeEncoderParams = encoderParams.ToNativePtr ();
411 st = GDIPlus.GdipSaveAdd (nativeObject, nativeEncoderParams);
412 Marshal.FreeHGlobal (nativeEncoderParams);
415 public void SaveAdd (Image image, EncoderParameters encoderParams)
417 Status st;
419 IntPtr nativeEncoderParams = encoderParams.ToNativePtr ();
420 st = GDIPlus.GdipSaveAddImage (nativeObject, image.NativeObject, nativeEncoderParams);
421 Marshal.FreeHGlobal (nativeEncoderParams);
424 public int SelectActiveFrame(FrameDimension dimension, int frameIndex)
426 Guid guid = dimension.Guid;
427 Status st = GDIPlus.GdipImageSelectActiveFrame (nativeObject, ref guid, frameIndex);
429 GDIPlus.CheckStatus (st);
431 return frameIndex;
434 public void SetPropertyItem(PropertyItem propitem)
436 IntPtr property;
437 int size = Marshal.SizeOf (typeof(GdipPropertyItem));
438 property = Marshal.AllocHGlobal (size);
440 Marshal.StructureToPtr (propitem, property, true);
441 Status status = GDIPlus.GdipSetPropertyItem (nativeObject, property);
442 GDIPlus.CheckStatus (status);
445 // properties
446 [Browsable (false)]
447 public int Flags {
448 get {
449 int flags;
451 Status status = GDIPlus.GdipGetImageFlags (nativeObject, out flags);
452 GDIPlus.CheckStatus (status);
453 return flags;
457 [Browsable (false)]
458 public Guid[] FrameDimensionsList {
459 get {
460 uint found;
461 Status status = GDIPlus.GdipImageGetFrameDimensionsCount (nativeObject, out found);
462 GDIPlus.CheckStatus (status);
463 Guid [] guid = new Guid [found];
464 status = GDIPlus.GdipImageGetFrameDimensionsList (nativeObject, guid, found);
465 GDIPlus.CheckStatus (status);
466 return guid;
470 [DefaultValue (false)]
471 [Browsable (false)]
472 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
473 public int Height {
474 get {
475 int height;
476 Status status = GDIPlus.GdipGetImageHeight (nativeObject, out height);
477 GDIPlus.CheckStatus (status);
479 return height;
483 public float HorizontalResolution {
484 get {
485 float resolution;
487 Status status = GDIPlus.GdipGetImageHorizontalResolution (nativeObject, out resolution);
488 GDIPlus.CheckStatus (status);
490 return resolution;
494 [Browsable (false)]
495 public ColorPalette Palette {
496 get {
498 return colorPalette;
500 set {
501 colorPalette = value;
505 public SizeF PhysicalDimension {
506 get {
507 float width, height;
508 Status status = GDIPlus.GdipGetImageDimension (nativeObject, out width, out height);
509 GDIPlus.CheckStatus (status);
511 return new SizeF (width, height);
515 public PixelFormat PixelFormat {
516 get {
517 PixelFormat pixFormat;
518 Status status = GDIPlus.GdipGetImagePixelFormat (nativeObject, out pixFormat);
519 GDIPlus.CheckStatus (status);
521 return pixFormat;
525 [Browsable (false)]
526 public int[] PropertyIdList {
527 get {
528 uint propNumbers;
530 Status status = GDIPlus.GdipGetPropertyCount (nativeObject,
531 out propNumbers);
532 GDIPlus.CheckStatus (status);
534 int [] idList = new int [propNumbers];
535 status = GDIPlus.GdipGetPropertyIdList (nativeObject,
536 propNumbers, idList);
537 GDIPlus.CheckStatus (status);
539 return idList;
543 [Browsable (false)]
544 public PropertyItem[] PropertyItems {
545 get {
546 int propNums, propsSize, propPtr, propSize;
547 IntPtr properties;
548 PropertyItem[] items;
549 GdipPropertyItem gdipProperty = new GdipPropertyItem ();
550 Status status;
552 status = GDIPlus.GdipGetPropertySize (nativeObject, out propsSize, out propNums);
553 GDIPlus.CheckStatus (status);
555 items = new PropertyItem [propNums];
557 if (propNums == 0)
558 return items;
560 /* Get PropertyItem list*/
561 properties = Marshal.AllocHGlobal (propsSize);
562 status = GDIPlus.GdipGetAllPropertyItems (nativeObject, propsSize,
563 propNums, properties);
564 GDIPlus.CheckStatus (status);
566 propSize = Marshal.SizeOf (gdipProperty);
567 propPtr = properties.ToInt32();
569 for (int i = 0; i < propNums; i++, propPtr += propSize)
571 gdipProperty = (GdipPropertyItem) Marshal.PtrToStructure
572 ((IntPtr)propPtr, typeof (GdipPropertyItem));
573 items [i] = new PropertyItem ();
574 GdipPropertyItem.MarshalTo (gdipProperty, items [i]);
577 Marshal.FreeHGlobal (properties);
578 return items;
582 public ImageFormat RawFormat {
583 get {
584 Guid guid;
585 Status st = GDIPlus.GdipGetImageRawFormat (nativeObject, out guid);
587 GDIPlus.CheckStatus (st);
588 return new ImageFormat (guid);
592 public Size Size {
593 get {
594 return new Size(Width, Height);
598 public float VerticalResolution {
599 get {
600 float resolution;
602 Status status = GDIPlus.GdipGetImageVerticalResolution (nativeObject, out resolution);
603 GDIPlus.CheckStatus (status);
605 return resolution;
609 [DefaultValue (false)]
610 [Browsable (false)]
611 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
612 public int Width {
613 get {
614 int width;
615 Status status = GDIPlus.GdipGetImageWidth (nativeObject, out width);
616 GDIPlus.CheckStatus (status);
618 return width;
622 internal IntPtr NativeObject{
623 get{
624 return nativeObject;
626 set {
627 nativeObject = value;
631 public void Dispose ()
633 Dispose (true);
634 System.GC.SuppressFinalize (this);
637 ~Image ()
639 Dispose (false);
642 private void DisposeResources ()
644 lock (this)
646 Status status = GDIPlus.GdipDisposeImage (nativeObject);
647 GDIPlus.CheckStatus (status);
651 protected virtual void Dispose (bool disposing)
653 if (nativeObject != IntPtr.Zero){
654 DisposeResources ();
655 nativeObject = IntPtr.Zero;
659 public virtual object Clone()
661 lock (this)
663 IntPtr newimage = IntPtr.Zero;
665 if (!(this is Bitmap))
666 throw new NotImplementedException ();
668 Status status = GDIPlus.GdipCloneImage (NativeObject, out newimage);
669 GDIPlus.CheckStatus (status);
671 if (this is Bitmap){
672 Bitmap b = new Bitmap (newimage);
674 if (colorPalette != null)
675 b.colorPalette = colorPalette.Clone ();
677 return b;
680 throw new NotImplementedException ();