2 // System.Drawing.Image.cs
4 // Authors: Christian Meyer (Christian.Meyer@cs.tum.edu)
5 // Alexandre Pigolkine (pigolkine@gmx.de)
6 // Jordi Mas i Hernandez (jordi@ximian.com)
7 // Sanjay Gupta (gsanjay@novell.com)
8 // Ravindra (rkumar@novell.com)
9 // Sebastien Pouliot <sebastien@ximian.com>
11 // Copyright (C) 2002 Ximian, Inc. http://www.ximian.com
12 // Copyright (C) 2004, 2007 Novell, Inc (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System
.Runtime
.Remoting
;
36 using System
.Runtime
.Serialization
;
37 using System
.Runtime
.InteropServices
;
38 using System
.ComponentModel
;
39 using System
.Drawing
.Imaging
;
41 using System
.Reflection
;
43 namespace System
.Drawing
47 [Editor ("System.Drawing.Design.ImageEditor, " + Consts
.AssemblySystem_Drawing_Design
, typeof (System
.Drawing
.Design
.UITypeEditor
))]
48 [TypeConverter (typeof(ImageConverter
))]
49 [ImmutableObject (true)]
50 public abstract class Image
: MarshalByRefObject
, IDisposable
, ICloneable
, ISerializable
52 public delegate bool GetThumbnailImageAbort();
57 internal IntPtr nativeObject
= IntPtr
.Zero
;
58 // when using MS GDI+ and IStream we must ensure the stream stays alive for all the life of the Image
59 // http://groups.google.com/group/microsoft.public.win32.programmer.gdi/browse_thread/thread/4967097db1469a27/4d36385b83532126?lnk=st&q=IStream+gdi&rnum=3&hl=en#4d36385b83532126
60 internal Stream stream
;
68 internal Image (SerializationInfo info
, StreamingContext context
)
70 foreach (SerializationEntry serEnum
in info
) {
71 if (String
.Compare(serEnum
.Name
, "Data", true) == 0) {
72 byte[] bytes
= (byte[]) serEnum
.Value
;
75 MemoryStream ms
= new MemoryStream (bytes
);
76 nativeObject
= InitFromStream (ms
);
77 // under Win32 stream is owned by SD/GDI+ code
78 if (GDIPlus
.RunningOnWindows ())
85 // FIXME - find out how metafiles (another decoder-only codec) are handled
86 void ISerializable
.GetObjectData (SerializationInfo si
, StreamingContext context
)
88 using (MemoryStream ms
= new MemoryStream ()) {
89 // Icon is a decoder-only codec
90 if (RawFormat
.Equals (ImageFormat
.Icon
)) {
91 Save (ms
, ImageFormat
.Png
);
95 si
.AddValue ("Data", ms
.ToArray ());
101 public static Image
FromFile(string filename
)
103 return FromFile (filename
, false);
106 public static Image
FromFile(string filename
, bool useEmbeddedColorManagement
)
111 if (!File
.Exists (filename
))
112 throw new FileNotFoundException (filename
);
114 if (useEmbeddedColorManagement
)
115 st
= GDIPlus
.GdipLoadImageFromFileICM (filename
, out imagePtr
);
117 st
= GDIPlus
.GdipLoadImageFromFile (filename
, out imagePtr
);
118 GDIPlus
.CheckStatus (st
);
120 return CreateFromHandle (imagePtr
);
123 public static Bitmap
FromHbitmap(IntPtr hbitmap
)
125 return FromHbitmap (hbitmap
, IntPtr
.Zero
);
128 public static Bitmap
FromHbitmap(IntPtr hbitmap
, IntPtr hpalette
)
133 st
= GDIPlus
.GdipCreateBitmapFromHBITMAP (hbitmap
, hpalette
, out imagePtr
);
135 GDIPlus
.CheckStatus (st
);
136 return new Bitmap (imagePtr
);
139 // note: FromStream can return either a Bitmap or Metafile instance
141 public static Image
FromStream (Stream stream
)
143 return LoadFromStream (stream
, false);
146 [MonoLimitation ("useEmbeddedColorManagement isn't supported.")]
147 public static Image
FromStream (Stream stream
, bool useEmbeddedColorManagement
)
149 return LoadFromStream (stream
, false);
152 // See http://support.microsoft.com/default.aspx?scid=kb;en-us;831419 for performance discussion
153 [MonoLimitation ("useEmbeddedColorManagement and validateImageData aren't supported.")]
154 public static Image
FromStream (Stream stream
, bool useEmbeddedColorManagement
, bool validateImageData
)
156 return LoadFromStream (stream
, false);
159 internal static Image
LoadFromStream (Stream stream
, bool keepAlive
)
162 throw new ArgumentNullException ("stream");
164 Image img
= CreateFromHandle (InitFromStream (stream
));
166 // Under Windows, we may need to keep a reference on the stream as long as the image is alive
167 // (GDI+ seems to use a lazy loader)
168 if (keepAlive
&& GDIPlus
.RunningOnWindows ())
174 internal static Image
CreateFromHandle (IntPtr handle
)
177 GDIPlus
.CheckStatus (GDIPlus
.GdipGetImageType (handle
, out type
));
179 case ImageType
.Bitmap
:
180 return new Bitmap (handle
);
181 case ImageType
.Metafile
:
182 return new Metafile (handle
);
184 throw new NotSupportedException (Locale
.GetText ("Unknown image type."));
188 public static int GetPixelFormatSize(PixelFormat pixfmt
)
192 case PixelFormat
.Format16bppArgb1555
:
193 case PixelFormat
.Format16bppGrayScale
:
194 case PixelFormat
.Format16bppRgb555
:
195 case PixelFormat
.Format16bppRgb565
:
198 case PixelFormat
.Format1bppIndexed
:
201 case PixelFormat
.Format24bppRgb
:
204 case PixelFormat
.Format32bppArgb
:
205 case PixelFormat
.Format32bppPArgb
:
206 case PixelFormat
.Format32bppRgb
:
209 case PixelFormat
.Format48bppRgb
:
212 case PixelFormat
.Format4bppIndexed
:
215 case PixelFormat
.Format64bppArgb
:
216 case PixelFormat
.Format64bppPArgb
:
219 case PixelFormat
.Format8bppIndexed
:
226 public static bool IsAlphaPixelFormat(PixelFormat pixfmt
)
230 case PixelFormat
.Format16bppArgb1555
:
231 case PixelFormat
.Format32bppArgb
:
232 case PixelFormat
.Format32bppPArgb
:
233 case PixelFormat
.Format64bppArgb
:
234 case PixelFormat
.Format64bppPArgb
:
237 case PixelFormat
.Format16bppGrayScale
:
238 case PixelFormat
.Format16bppRgb555
:
239 case PixelFormat
.Format16bppRgb565
:
240 case PixelFormat
.Format1bppIndexed
:
241 case PixelFormat
.Format24bppRgb
:
242 case PixelFormat
.Format32bppRgb
:
243 case PixelFormat
.Format48bppRgb
:
244 case PixelFormat
.Format4bppIndexed
:
245 case PixelFormat
.Format8bppIndexed
:
252 public static bool IsCanonicalPixelFormat (PixelFormat pixfmt
)
254 return ((pixfmt
& PixelFormat
.Canonical
) != 0);
257 public static bool IsExtendedPixelFormat (PixelFormat pixfmt
)
259 return ((pixfmt
& PixelFormat
.Extended
) != 0);
262 internal static IntPtr
InitFromStream (Stream stream
)
265 throw new ArgumentException ("stream");
271 if (!stream
.CanSeek
) {
272 byte[] buffer
= new byte[256];
277 if (buffer
.Length
< index
+ 256) {
278 byte[] newBuffer
= new byte[buffer
.Length
* 2];
279 Array
.Copy(buffer
, newBuffer
, buffer
.Length
);
282 count
= stream
.Read(buffer
, index
, 256);
287 stream
= new MemoryStream(buffer
, 0, index
);
290 if (GDIPlus
.RunningOnUnix ()) {
291 // Unix, with libgdiplus
292 // We use a custom API for this, because there's no easy way
293 // to get the Stream down to libgdiplus. So, we wrap the stream
294 // with a set of delegates.
295 GDIPlus
.GdiPlusStreamHelper sh
= new GDIPlus
.GdiPlusStreamHelper (stream
, true);
297 st
= GDIPlus
.GdipLoadImageFromDelegate_linux (sh
.GetHeaderDelegate
, sh
.GetBytesDelegate
,
298 sh
.PutBytesDelegate
, sh
.SeekDelegate
, sh
.CloseDelegate
, sh
.SizeDelegate
, out imagePtr
);
300 st
= GDIPlus
.GdipLoadImageFromStream (new ComIStreamWrapper (stream
), out imagePtr
);
303 GDIPlus
.CheckStatus (st
);
308 public RectangleF
GetBounds (ref GraphicsUnit pageUnit
)
312 Status status
= GDIPlus
.GdipGetImageBounds (nativeObject
, out source
, ref pageUnit
);
313 GDIPlus
.CheckStatus (status
);
318 public EncoderParameters
GetEncoderParameterList(Guid encoder
)
323 status
= GDIPlus
.GdipGetEncoderParameterListSize (nativeObject
, ref encoder
, out sz
);
324 GDIPlus
.CheckStatus (status
);
326 IntPtr rawEPList
= Marshal
.AllocHGlobal ((int) sz
);
327 EncoderParameters eps
;
330 status
= GDIPlus
.GdipGetEncoderParameterList (nativeObject
, ref encoder
, sz
, rawEPList
);
331 eps
= EncoderParameters
.FromNativePtr (rawEPList
);
332 GDIPlus
.CheckStatus (status
);
335 Marshal
.FreeHGlobal (rawEPList
);
341 public int GetFrameCount (FrameDimension dimension
)
344 Guid guid
= dimension
.Guid
;
346 Status status
= GDIPlus
.GdipImageGetFrameCount (nativeObject
, ref guid
, out count
);
347 GDIPlus
.CheckStatus (status
);
352 public PropertyItem
GetPropertyItem(int propid
)
356 PropertyItem item
= new PropertyItem ();
357 GdipPropertyItem gdipProperty
= new GdipPropertyItem ();
360 status
= GDIPlus
.GdipGetPropertyItemSize (nativeObject
, propid
,
362 GDIPlus
.CheckStatus (status
);
364 /* Get PropertyItem */
365 property
= Marshal
.AllocHGlobal (propSize
);
367 status
= GDIPlus
.GdipGetPropertyItem (nativeObject
, propid
, propSize
, property
);
368 GDIPlus
.CheckStatus (status
);
369 gdipProperty
= (GdipPropertyItem
) Marshal
.PtrToStructure (property
,
370 typeof (GdipPropertyItem
));
371 GdipPropertyItem
.MarshalTo (gdipProperty
, item
);
374 Marshal
.FreeHGlobal (property
);
379 public Image
GetThumbnailImage (int thumbWidth
, int thumbHeight
, Image
.GetThumbnailImageAbort callback
, IntPtr callbackData
)
381 if ((thumbWidth
<= 0) || (thumbHeight
<= 0))
382 throw new OutOfMemoryException ("Invalid thumbnail size");
384 Image ThumbNail
= new Bitmap (thumbWidth
, thumbHeight
);
386 using (Graphics g
= Graphics
.FromImage (ThumbNail
)) {
387 Status status
= GDIPlus
.GdipDrawImageRectRectI (g
.nativeObject
, nativeObject
,
388 0, 0, thumbWidth
, thumbHeight
,
389 0, 0, this.Width
, this.Height
,
390 GraphicsUnit
.Pixel
, IntPtr
.Zero
, null, IntPtr
.Zero
);
392 GDIPlus
.CheckStatus (status
);
399 public void RemovePropertyItem (int propid
)
401 Status status
= GDIPlus
.GdipRemovePropertyItem (nativeObject
, propid
);
402 GDIPlus
.CheckStatus (status
);
405 public void RotateFlip (RotateFlipType rotateFlipType
)
407 Status status
= GDIPlus
.GdipImageRotateFlip (nativeObject
, rotateFlipType
);
408 GDIPlus
.CheckStatus (status
);
411 internal ImageCodecInfo
findEncoderForFormat (ImageFormat format
)
413 ImageCodecInfo
[] encoders
= ImageCodecInfo
.GetImageEncoders();
414 ImageCodecInfo encoder
= null;
416 if (format
.Guid
.Equals (ImageFormat
.MemoryBmp
.Guid
))
417 format
= ImageFormat
.Png
;
419 /* Look for the right encoder for our format*/
420 for (int i
= 0; i
< encoders
.Length
; i
++) {
421 if (encoders
[i
].FormatID
.Equals (format
.Guid
)) {
422 encoder
= encoders
[i
];
430 public void Save (string filename
)
432 Save (filename
, RawFormat
);
435 public void Save(string filename
, ImageFormat format
)
437 ImageCodecInfo encoder
= findEncoderForFormat (format
);
438 if (encoder
== null) {
440 encoder
= findEncoderForFormat (RawFormat
);
441 if (encoder
== null) {
442 string msg
= Locale
.GetText ("No codec available for saving format '{0}'.", format
.Guid
);
443 throw new ArgumentException (msg
, "format");
446 Save (filename
, encoder
, null);
449 public void Save(string filename
, ImageCodecInfo encoder
, EncoderParameters encoderParams
)
452 Guid guid
= encoder
.Clsid
;
454 if (encoderParams
== null) {
455 st
= GDIPlus
.GdipSaveImageToFile (nativeObject
, filename
, ref guid
, IntPtr
.Zero
);
457 IntPtr nativeEncoderParams
= encoderParams
.ToNativePtr ();
458 st
= GDIPlus
.GdipSaveImageToFile (nativeObject
, filename
, ref guid
, nativeEncoderParams
);
459 Marshal
.FreeHGlobal (nativeEncoderParams
);
462 GDIPlus
.CheckStatus (st
);
465 public void Save (Stream stream
, ImageFormat format
)
467 ImageCodecInfo encoder
= findEncoderForFormat (format
);
470 throw new ArgumentException ("No codec available for format:" + format
.Guid
);
472 Save (stream
, encoder
, null);
475 public void Save(Stream stream
, ImageCodecInfo encoder
, EncoderParameters encoderParams
)
478 IntPtr nativeEncoderParams
;
479 Guid guid
= encoder
.Clsid
;
481 if (encoderParams
== null)
482 nativeEncoderParams
= IntPtr
.Zero
;
484 nativeEncoderParams
= encoderParams
.ToNativePtr ();
487 if (GDIPlus
.RunningOnUnix ()) {
488 GDIPlus
.GdiPlusStreamHelper sh
= new GDIPlus
.GdiPlusStreamHelper (stream
, false);
489 st
= GDIPlus
.GdipSaveImageToDelegate_linux (nativeObject
, sh
.GetBytesDelegate
, sh
.PutBytesDelegate
,
490 sh
.SeekDelegate
, sh
.CloseDelegate
, sh
.SizeDelegate
, ref guid
, nativeEncoderParams
);
492 st
= GDIPlus
.GdipSaveImageToStream (new HandleRef (this, nativeObject
),
493 new ComIStreamWrapper (stream
), ref guid
, new HandleRef (encoderParams
, nativeEncoderParams
));
497 if (nativeEncoderParams
!= IntPtr
.Zero
)
498 Marshal
.FreeHGlobal (nativeEncoderParams
);
501 GDIPlus
.CheckStatus (st
);
504 public void SaveAdd (EncoderParameters encoderParams
)
508 IntPtr nativeEncoderParams
= encoderParams
.ToNativePtr ();
509 st
= GDIPlus
.GdipSaveAdd (nativeObject
, nativeEncoderParams
);
510 Marshal
.FreeHGlobal (nativeEncoderParams
);
511 GDIPlus
.CheckStatus (st
);
514 public void SaveAdd (Image image
, EncoderParameters encoderParams
)
518 IntPtr nativeEncoderParams
= encoderParams
.ToNativePtr ();
519 st
= GDIPlus
.GdipSaveAddImage (nativeObject
, image
.NativeObject
, nativeEncoderParams
);
520 Marshal
.FreeHGlobal (nativeEncoderParams
);
521 GDIPlus
.CheckStatus (st
);
524 public int SelectActiveFrame(FrameDimension dimension
, int frameIndex
)
526 Guid guid
= dimension
.Guid
;
527 Status st
= GDIPlus
.GdipImageSelectActiveFrame (nativeObject
, ref guid
, frameIndex
);
529 GDIPlus
.CheckStatus (st
);
534 public void SetPropertyItem(PropertyItem propitem
)
536 throw new NotImplementedException ();
538 GdipPropertyItem pi = new GdipPropertyItem ();
539 GdipPropertyItem.MarshalTo (pi, propitem);
541 Status status = GDIPlus.GdipSetPropertyItem (nativeObject, &pi);
543 GDIPlus.CheckStatus (status);
554 Status status
= GDIPlus
.GdipGetImageFlags (nativeObject
, out flags
);
555 GDIPlus
.CheckStatus (status
);
561 public Guid
[] FrameDimensionsList
{
564 Status status
= GDIPlus
.GdipImageGetFrameDimensionsCount (nativeObject
, out found
);
565 GDIPlus
.CheckStatus (status
);
566 Guid
[] guid
= new Guid
[found
];
567 status
= GDIPlus
.GdipImageGetFrameDimensionsList (nativeObject
, guid
, found
);
568 GDIPlus
.CheckStatus (status
);
573 [DefaultValue (false)]
575 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
579 Status status
= GDIPlus
.GdipGetImageHeight (nativeObject
, out height
);
580 GDIPlus
.CheckStatus (status
);
586 public float HorizontalResolution
{
590 Status status
= GDIPlus
.GdipGetImageHorizontalResolution (nativeObject
, out resolution
);
591 GDIPlus
.CheckStatus (status
);
598 public ColorPalette Palette
{
600 return retrieveGDIPalette();
603 storeGDIPalette(value);
607 internal ColorPalette
retrieveGDIPalette()
610 ColorPalette ret
= new ColorPalette ();
612 Status st
= GDIPlus
.GdipGetImagePaletteSize (nativeObject
, out bytes
);
613 GDIPlus
.CheckStatus (st
);
614 IntPtr palette_data
= Marshal
.AllocHGlobal (bytes
);
616 st
= GDIPlus
.GdipGetImagePalette (nativeObject
, palette_data
, bytes
);
617 GDIPlus
.CheckStatus (st
);
618 ret
.setFromGDIPalette (palette_data
);
623 Marshal
.FreeHGlobal (palette_data
);
627 internal void storeGDIPalette(ColorPalette palette
)
629 if (palette
== null) {
630 throw new ArgumentNullException("palette");
632 IntPtr palette_data
= palette
.getGDIPalette();
633 if (palette_data
== IntPtr
.Zero
) {
638 Status st
= GDIPlus
.GdipSetImagePalette (nativeObject
, palette_data
);
639 GDIPlus
.CheckStatus (st
);
643 Marshal
.FreeHGlobal(palette_data
);
648 public SizeF PhysicalDimension
{
651 Status status
= GDIPlus
.GdipGetImageDimension (nativeObject
, out width
, out height
);
652 GDIPlus
.CheckStatus (status
);
654 return new SizeF (width
, height
);
658 public PixelFormat PixelFormat
{
660 PixelFormat pixFormat
;
661 Status status
= GDIPlus
.GdipGetImagePixelFormat (nativeObject
, out pixFormat
);
662 GDIPlus
.CheckStatus (status
);
669 public int[] PropertyIdList
{
673 Status status
= GDIPlus
.GdipGetPropertyCount (nativeObject
,
675 GDIPlus
.CheckStatus (status
);
677 int [] idList
= new int [propNumbers
];
678 status
= GDIPlus
.GdipGetPropertyIdList (nativeObject
,
679 propNumbers
, idList
);
680 GDIPlus
.CheckStatus (status
);
687 public PropertyItem
[] PropertyItems
{
689 int propNums
, propsSize
, propSize
;
690 IntPtr properties
, propPtr
;
691 PropertyItem
[] items
;
692 GdipPropertyItem gdipProperty
= new GdipPropertyItem ();
695 status
= GDIPlus
.GdipGetPropertySize (nativeObject
, out propsSize
, out propNums
);
696 GDIPlus
.CheckStatus (status
);
698 items
= new PropertyItem
[propNums
];
703 /* Get PropertyItem list*/
704 properties
= Marshal
.AllocHGlobal (propsSize
* propNums
);
706 status
= GDIPlus
.GdipGetAllPropertyItems (nativeObject
, propsSize
,
707 propNums
, properties
);
708 GDIPlus
.CheckStatus (status
);
710 propSize
= Marshal
.SizeOf (gdipProperty
);
711 propPtr
= properties
;
713 for (int i
= 0; i
< propNums
; i
++, propPtr
= new IntPtr (propPtr
.ToInt64 () + propSize
)) {
714 gdipProperty
= (GdipPropertyItem
) Marshal
.PtrToStructure
715 (propPtr
, typeof (GdipPropertyItem
));
716 items
[i
] = new PropertyItem ();
717 GdipPropertyItem
.MarshalTo (gdipProperty
, items
[i
]);
721 Marshal
.FreeHGlobal (properties
);
727 public ImageFormat RawFormat
{
730 Status st
= GDIPlus
.GdipGetImageRawFormat (nativeObject
, out guid
);
732 GDIPlus
.CheckStatus (st
);
733 return new ImageFormat (guid
);
739 return new Size(Width
, Height
);
744 [DefaultValue (null)]
745 [LocalizableAttribute(false)]
746 [BindableAttribute(true)]
747 [TypeConverter (typeof (StringConverter
))]
753 public float VerticalResolution
{
757 Status status
= GDIPlus
.GdipGetImageVerticalResolution (nativeObject
, out resolution
);
758 GDIPlus
.CheckStatus (status
);
764 [DefaultValue (false)]
766 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
770 Status status
= GDIPlus
.GdipGetImageWidth (nativeObject
, out width
);
771 GDIPlus
.CheckStatus (status
);
777 internal IntPtr NativeObject
{
782 nativeObject
= value;
786 public void Dispose ()
789 System
.GC
.SuppressFinalize (this);
797 protected virtual void Dispose (bool disposing
)
799 if (GDIPlus
.GdiPlusToken
!= 0 && nativeObject
!= IntPtr
.Zero
) {
800 Status status
= GDIPlus
.GdipDisposeImage (nativeObject
);
801 // dispose the stream (set under Win32 only if SD owns the stream) and ...
802 if (stream
!= null) {
806 // ... set nativeObject to null before (possibly) throwing an exception
807 nativeObject
= IntPtr
.Zero
;
808 GDIPlus
.CheckStatus (status
);
812 public object Clone ()
814 if (GDIPlus
.RunningOnWindows () && stream
!= null)
815 return CloneFromStream ();
817 IntPtr newimage
= IntPtr
.Zero
;
818 Status status
= GDIPlus
.GdipCloneImage (NativeObject
, out newimage
);
819 GDIPlus
.CheckStatus (status
);
822 return new Bitmap (newimage
);
824 return new Metafile (newimage
);
827 // On win32, when cloning images that were originally created from a stream, we need to
828 // clone both the image and the stream to make sure the gc doesn't kill it
829 // (when using MS GDI+ and IStream we must ensure the stream stays alive for all the life of the Image)
830 object CloneFromStream ()
832 byte[] bytes
= new byte [stream
.Length
];
833 MemoryStream ms
= new MemoryStream (bytes
);
834 int count
= (stream
.Length
< 4096 ? (int) stream
.Length
: 4096);
835 byte[] buffer
= new byte[count
];
838 count
= stream
.Read (buffer
, 0, count
);
839 ms
.Write (buffer
, 0, count
);
840 } while (count
== 4096);
842 IntPtr newimage
= IntPtr
.Zero
;
843 newimage
= InitFromStream (ms
);
846 return new Bitmap (newimage
, ms
);
848 return new Metafile (newimage
, ms
);