2 // System.Drawing.Image.cs
4 // Copyright (C) 2002 Ximian, Inc. http://www.ximian.com
5 // Copyright (C) 2004 Novell, Inc. http://www.novell.com
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:
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
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.
38 using System.Runtime.Remoting;
39 using System.Runtime.Serialization;
40 using System.Runtime.InteropServices;
41 using System.ComponentModel;
42 using System.Drawing.Imaging;
45 namespace System.Drawing
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;
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;
73 InitFromStream(new MemoryStream(bytes));
80 void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
82 throw new NotImplementedException();
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);
98 public static Bitmap FromHbitmap(IntPtr hbitmap)
100 throw new NotImplementedException ();
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)
123 case PixelFormat.Format16bppArgb1555:
124 case PixelFormat.Format16bppGrayScale:
125 case PixelFormat.Format16bppRgb555:
126 case PixelFormat.Format16bppRgb565:
129 case PixelFormat.Format1bppIndexed:
132 case PixelFormat.Format24bppRgb:
135 case PixelFormat.Format32bppArgb:
136 case PixelFormat.Format32bppPArgb:
137 case PixelFormat.Format32bppRgb:
140 case PixelFormat.Format48bppRgb:
143 case PixelFormat.Format4bppIndexed:
146 case PixelFormat.Format64bppArgb:
147 case PixelFormat.Format64bppPArgb:
150 case PixelFormat.Format8bppIndexed:
157 public static bool IsAlphaPixelFormat(PixelFormat pixfmt)
161 case PixelFormat.Format16bppArgb1555:
162 case PixelFormat.Format32bppArgb:
163 case PixelFormat.Format32bppPArgb:
164 case PixelFormat.Format64bppArgb:
165 case PixelFormat.Format64bppPArgb:
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:
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);
203 Status st = GDIPlus.GdipLoadImageFromDelegate_linux (sh.GetBytesDelegate, sh.PutBytesDelegate,
204 sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate,
206 GDIPlus.CheckStatus (st);
207 nativeObject = imagePtr;
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)");
220 public RectangleF GetBounds (ref GraphicsUnit pageUnit)
224 Status status = GDIPlus.GdipGetImageBounds (nativeObject, out source, ref pageUnit);
225 GDIPlus.CheckStatus (status);
230 public EncoderParameters GetEncoderParameterList(Guid format)
235 status = GDIPlus.GdipGetEncoderParameterListSize (nativeObject, ref format, out sz);
236 GDIPlus.CheckStatus (status);
238 IntPtr rawEPList = Marshal.AllocHGlobal ((int) sz);
239 EncoderParameters eps;
242 status = GDIPlus.GdipGetEncoderParameterList (nativeObject, ref format, sz, rawEPList);
243 eps = EncoderParameters.FromNativePtr (rawEPList);
244 GDIPlus.CheckStatus (status);
246 Marshal.FreeHGlobal (rawEPList);
250 Marshal.FreeHGlobal (rawEPList);
255 public int GetFrameCount(FrameDimension dimension)
258 Guid guid = dimension.Guid;
259 Status status = GDIPlus.GdipImageGetFrameCount (nativeObject, ref guid, out count);
261 GDIPlus.CheckStatus (status);
267 public PropertyItem GetPropertyItem(int propid)
271 PropertyItem item = new PropertyItem ();
272 GdipPropertyItem gdipProperty = new GdipPropertyItem ();
275 status = GDIPlus.GdipGetPropertyItemSize (nativeObject, propid,
277 GDIPlus.CheckStatus (status);
279 /* Get PropertyItem */
280 property = Marshal.AllocHGlobal (propSize);
281 status = GDIPlus.GdipGetPropertyItem (nativeObject, propid, propSize,
283 GDIPlus.CheckStatus (status);
284 gdipProperty = (GdipPropertyItem) Marshal.PtrToStructure ((IntPtr)property,
285 typeof (GdipPropertyItem));
286 GdipPropertyItem.MarshalTo (gdipProperty, item);
288 Marshal.FreeHGlobal (property);
292 public Image GetThumbnailImage(int thumbWidth, int thumbHeight, Image.GetThumbnailImageAbort callback, IntPtr callbackData)
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);
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];
343 public void Save (string filename)
345 Save (filename, RawFormat);
348 public void Save(string filename, ImageFormat format)
350 ImageCodecInfo encoder = findEncoderForFormat (format);
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)
361 Guid guid = encoder.Clsid;
363 if (encoderParams == null) {
364 st = GDIPlus.GdipSaveImageToFile (nativeObject, filename, ref guid, IntPtr.Zero);
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);
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)
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);
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);
401 throw new NotImplementedException ("Image.Save(Stream) (win32)");
403 GDIPlus.CheckStatus (st);
406 public void SaveAdd (EncoderParameters encoderParams)
410 IntPtr nativeEncoderParams = encoderParams.ToNativePtr ();
411 st = GDIPlus.GdipSaveAdd (nativeObject, nativeEncoderParams);
412 Marshal.FreeHGlobal (nativeEncoderParams);
\r
413 GDIPlus.CheckStatus (st);
416 public void SaveAdd (Image image, EncoderParameters encoderParams)
420 IntPtr nativeEncoderParams = encoderParams.ToNativePtr ();
421 st = GDIPlus.GdipSaveAddImage (nativeObject, image.NativeObject, nativeEncoderParams);
422 Marshal.FreeHGlobal (nativeEncoderParams);
\r
423 GDIPlus.CheckStatus (st);
426 public int SelectActiveFrame(FrameDimension dimension, int frameIndex)
428 Guid guid = dimension.Guid;
429 Status st = GDIPlus.GdipImageSelectActiveFrame (nativeObject, ref guid, frameIndex);
431 GDIPlus.CheckStatus (st);
436 public void SetPropertyItem(PropertyItem propitem)
439 int size = Marshal.SizeOf (typeof(GdipPropertyItem));
440 property = Marshal.AllocHGlobal (size);
442 Marshal.StructureToPtr (propitem, property, true);
443 Status status = GDIPlus.GdipSetPropertyItem (nativeObject, property);
444 GDIPlus.CheckStatus (status);
453 Status status = GDIPlus.GdipGetImageFlags (nativeObject, out flags);
454 GDIPlus.CheckStatus (status);
460 public Guid[] FrameDimensionsList {
463 Status status = GDIPlus.GdipImageGetFrameDimensionsCount (nativeObject, out found);
464 GDIPlus.CheckStatus (status);
465 Guid [] guid = new Guid [found];
466 status = GDIPlus.GdipImageGetFrameDimensionsList (nativeObject, guid, found);
467 GDIPlus.CheckStatus (status);
472 [DefaultValue (false)]
474 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
478 Status status = GDIPlus.GdipGetImageHeight (nativeObject, out height);
479 GDIPlus.CheckStatus (status);
485 public float HorizontalResolution {
489 Status status = GDIPlus.GdipGetImageHorizontalResolution (nativeObject, out resolution);
490 GDIPlus.CheckStatus (status);
497 public ColorPalette Palette {
503 colorPalette = value;
507 public SizeF PhysicalDimension {
510 Status status = GDIPlus.GdipGetImageDimension (nativeObject, out width, out height);
511 GDIPlus.CheckStatus (status);
513 return new SizeF (width, height);
517 public PixelFormat PixelFormat {
519 PixelFormat pixFormat;
520 Status status = GDIPlus.GdipGetImagePixelFormat (nativeObject, out pixFormat);
521 GDIPlus.CheckStatus (status);
528 public int[] PropertyIdList {
532 Status status = GDIPlus.GdipGetPropertyCount (nativeObject,
534 GDIPlus.CheckStatus (status);
536 int [] idList = new int [propNumbers];
537 status = GDIPlus.GdipGetPropertyIdList (nativeObject,
538 propNumbers, idList);
539 GDIPlus.CheckStatus (status);
546 public PropertyItem[] PropertyItems {
548 int propNums, propsSize, propSize;
549 IntPtr properties, propPtr;
550 PropertyItem[] items;
551 GdipPropertyItem gdipProperty = new GdipPropertyItem ();
554 status = GDIPlus.GdipGetPropertySize (nativeObject, out propsSize, out propNums);
555 GDIPlus.CheckStatus (status);
557 items = new PropertyItem [propNums];
562 /* Get PropertyItem list*/
563 properties = Marshal.AllocHGlobal (propsSize);
564 status = GDIPlus.GdipGetAllPropertyItems (nativeObject, propsSize,
565 propNums, properties);
566 GDIPlus.CheckStatus (status);
568 propSize = Marshal.SizeOf (gdipProperty);
569 propPtr = properties;
571 for (int i = 0; i < propNums; i++, propPtr = new IntPtr (propPtr.ToInt64 () + propSize))
573 gdipProperty = (GdipPropertyItem) Marshal.PtrToStructure
574 (propPtr, typeof (GdipPropertyItem));
575 items [i] = new PropertyItem ();
576 GdipPropertyItem.MarshalTo (gdipProperty, items [i]);
579 Marshal.FreeHGlobal (properties);
584 public ImageFormat RawFormat {
587 Status st = GDIPlus.GdipGetImageRawFormat (nativeObject, out guid);
589 GDIPlus.CheckStatus (st);
590 return new ImageFormat (guid);
596 return new Size(Width, Height);
600 public float VerticalResolution {
604 Status status = GDIPlus.GdipGetImageVerticalResolution (nativeObject, out resolution);
605 GDIPlus.CheckStatus (status);
611 [DefaultValue (false)]
613 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
617 Status status = GDIPlus.GdipGetImageWidth (nativeObject, out width);
618 GDIPlus.CheckStatus (status);
624 internal IntPtr NativeObject{
629 nativeObject = value;
633 public void Dispose ()
636 System.GC.SuppressFinalize (this);
644 private void DisposeResources ()
648 Status status = GDIPlus.GdipDisposeImage (nativeObject);
649 GDIPlus.CheckStatus (status);
653 protected virtual void Dispose (bool disposing)
655 if (nativeObject != IntPtr.Zero){
657 nativeObject = IntPtr.Zero;
661 public virtual object Clone()
665 IntPtr newimage = IntPtr.Zero;
667 if (!(this is Bitmap))
668 throw new NotImplementedException ();
670 Status status = GDIPlus.GdipCloneImage (NativeObject, out newimage);
671 GDIPlus.CheckStatus (status);
674 Bitmap b = new Bitmap (newimage);
676 if (colorPalette != null)
677 b.colorPalette = colorPalette.Clone ();
682 throw new NotImplementedException ();