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
);
415 public void SaveAdd (Image image
, EncoderParameters encoderParams
)
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
);
434 public void SetPropertyItem(PropertyItem propitem
)
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
);
451 Status status
= GDIPlus
.GdipGetImageFlags (nativeObject
, out flags
);
452 GDIPlus
.CheckStatus (status
);
458 public Guid
[] FrameDimensionsList
{
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
);
470 [DefaultValue (false)]
472 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
476 Status status
= GDIPlus
.GdipGetImageHeight (nativeObject
, out height
);
477 GDIPlus
.CheckStatus (status
);
483 public float HorizontalResolution
{
487 Status status
= GDIPlus
.GdipGetImageHorizontalResolution (nativeObject
, out resolution
);
488 GDIPlus
.CheckStatus (status
);
495 public ColorPalette Palette
{
501 colorPalette
= value;
505 public SizeF PhysicalDimension
{
508 Status status
= GDIPlus
.GdipGetImageDimension (nativeObject
, out width
, out height
);
509 GDIPlus
.CheckStatus (status
);
511 return new SizeF (width
, height
);
515 public PixelFormat PixelFormat
{
517 PixelFormat pixFormat
;
518 Status status
= GDIPlus
.GdipGetImagePixelFormat (nativeObject
, out pixFormat
);
519 GDIPlus
.CheckStatus (status
);
526 public int[] PropertyIdList
{
530 Status status
= GDIPlus
.GdipGetPropertyCount (nativeObject
,
532 GDIPlus
.CheckStatus (status
);
534 int [] idList
= new int [propNumbers
];
535 status
= GDIPlus
.GdipGetPropertyIdList (nativeObject
,
536 propNumbers
, idList
);
537 GDIPlus
.CheckStatus (status
);
544 public PropertyItem
[] PropertyItems
{
546 int propNums
, propsSize
, propPtr
, propSize
;
548 PropertyItem
[] items
;
549 GdipPropertyItem gdipProperty
= new GdipPropertyItem ();
552 status
= GDIPlus
.GdipGetPropertySize (nativeObject
, out propsSize
, out propNums
);
553 GDIPlus
.CheckStatus (status
);
555 items
= new PropertyItem
[propNums
];
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
);
582 public ImageFormat RawFormat
{
585 Status st
= GDIPlus
.GdipGetImageRawFormat (nativeObject
, out guid
);
587 GDIPlus
.CheckStatus (st
);
588 return new ImageFormat (guid
);
594 return new Size(Width
, Height
);
598 public float VerticalResolution
{
602 Status status
= GDIPlus
.GdipGetImageVerticalResolution (nativeObject
, out resolution
);
603 GDIPlus
.CheckStatus (status
);
609 [DefaultValue (false)]
611 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
615 Status status
= GDIPlus
.GdipGetImageWidth (nativeObject
, out width
);
616 GDIPlus
.CheckStatus (status
);
622 internal IntPtr NativeObject
{
627 nativeObject
= value;
631 public void Dispose ()
634 System
.GC
.SuppressFinalize (this);
642 private void DisposeResources ()
646 Status status
= GDIPlus
.GdipDisposeImage (nativeObject
);
647 GDIPlus
.CheckStatus (status
);
651 protected virtual void Dispose (bool disposing
)
653 if (nativeObject
!= IntPtr
.Zero
){
655 nativeObject
= IntPtr
.Zero
;
659 public virtual object Clone()
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
);
672 Bitmap b
= new Bitmap (newimage
);
674 if (colorPalette
!= null)
675 b
.colorPalette
= colorPalette
.Clone ();
680 throw new NotImplementedException ();