importing messaging-2008 branch to trunk.
[mono.git] / mcs / class / System.Drawing / System.Drawing / Bitmap.cs
1 //
2 // System.Drawing.Bitmap.cs
3 //
4 // Copyright (C) 2002 Ximian, Inc.  http://www.ximian.com
5 // Copyright (C) 2004 Novell, Inc.  http://www.novell.com
6 //
7 // Authors: 
8 //      Alexandre Pigolkine (pigolkine@gmx.de)
9 //      Christian Meyer (Christian.Meyer@cs.tum.edu)
10 //      Miguel de Icaza (miguel@ximian.com)
11 //      Jordi Mas i Hernandez (jmas@softcatala.org)
12 //      Ravindra (rkumar@novell.com)
13 //
14
15 //
16 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
17 //
18 // Permission is hereby granted, free of charge, to any person obtaining
19 // a copy of this software and associated documentation files (the
20 // "Software"), to deal in the Software without restriction, including
21 // without limitation the rights to use, copy, modify, merge, publish,
22 // distribute, sublicense, and/or sell copies of the Software, and to
23 // permit persons to whom the Software is furnished to do so, subject to
24 // the following conditions:
25 // 
26 // The above copyright notice and this permission notice shall be
27 // included in all copies or substantial portions of the Software.
28 // 
29 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 //
37
38 using System.IO;
39 using System.Drawing.Imaging;
40 using System.Runtime.Serialization;
41 using System.Runtime.InteropServices;
42 using System.ComponentModel;
43 using System.Security.Permissions;
44
45 namespace System.Drawing
46 {
47         [Serializable]
48         [ComVisible (true)]
49         [Editor ("System.Drawing.Design.BitmapEditor, " + Consts.AssemblySystem_Drawing_Design, typeof (System.Drawing.Design.UITypeEditor))]
50         public sealed class Bitmap : Image
51         {
52                 #region constructors
53                 // constructors
54
55 #if NET_2_0
56                 // required for XmlSerializer (#323246)
57                 private Bitmap ()
58                 {
59                 }
60 #endif
61
62                 internal Bitmap (IntPtr ptr)
63                 {
64                         nativeObject = ptr;
65                 }
66
67                 // Usually called when cloning images that need to have
68                 // not only the handle saved, but also the underlying stream
69                 // (when using MS GDI+ and IStream we must ensure the stream stays alive for all the life of the Image)
70                 internal Bitmap(IntPtr ptr, Stream stream)
71                 {
72                         // under Win32 stream is owned by SD/GDI+ code
73                         if (GDIPlus.RunningOnWindows ())
74                                 this.stream = stream;
75                         nativeObject = ptr;
76                 }
77
78                 public Bitmap (int width, int height) : this (width, height, PixelFormat.Format32bppArgb)
79                 {
80                 }
81
82                 public Bitmap (int width, int height, Graphics g)
83                 {
84                         if (g == null)
85                                 throw new ArgumentNullException ("g");
86
87                         IntPtr bmp;
88                         Status s = GDIPlus.GdipCreateBitmapFromGraphics (width, height, g.nativeObject, out bmp);
89                         GDIPlus.CheckStatus (s);
90                         nativeObject = bmp;                                             
91                 }
92
93                 public Bitmap (int width, int height, PixelFormat format)
94                 {       
95                         IntPtr bmp;
96                         Status s = GDIPlus.GdipCreateBitmapFromScan0 (width, height, 0, format, IntPtr.Zero, out bmp);
97                         GDIPlus.CheckStatus (s);
98                         nativeObject = bmp;
99                         
100                 }
101
102                 public Bitmap (Image original) : this (original, original.Width, original.Height) {}
103
104                 public Bitmap (Stream stream)  : this (stream, false) {} 
105
106                 public Bitmap (string filename) : this (filename, false) {}
107
108                 public Bitmap (Image original, Size newSize)  : this(original, newSize.Width, newSize.Height) {}
109                 
110                 public Bitmap (Stream stream, bool useIcm)
111                 {
112                         // false: stream is owned by user code
113                         nativeObject = InitFromStream (stream);
114                 }
115
116                 public Bitmap (string filename, bool useIcm)
117                 {
118                         if (filename == null)
119                                 throw new ArgumentNullException ("filename");
120
121                         IntPtr imagePtr;
122                         Status st;
123
124                         if (useIcm)
125                                 st = GDIPlus.GdipCreateBitmapFromFileICM (filename, out imagePtr);
126                         else
127                                 st = GDIPlus.GdipCreateBitmapFromFile (filename, out imagePtr);
128
129                         GDIPlus.CheckStatus (st);
130                         nativeObject = imagePtr;
131                 }
132
133                 public Bitmap (Type type, string resource)
134                 {
135                         if (resource == null)
136                                 throw new ArgumentException ("resource");
137
138                         Stream s = type.Assembly.GetManifestResourceStream (type, resource);
139                         if (s == null) {
140                                 string msg = Locale.GetText ("Resource '{0}' was not found.", resource);
141                                 throw new FileNotFoundException (msg);
142                         }
143
144                         nativeObject = InitFromStream (s);
145                         // under Win32 stream is owned by SD/GDI+ code
146                         if (GDIPlus.RunningOnWindows ())
147                                 stream = s;
148                 }
149
150                 public Bitmap (Image original, int width, int height)  : this(width, height, PixelFormat.Format32bppArgb)
151                 {
152                         Graphics graphics = Graphics.FromImage(this);
153
154                         graphics.DrawImage(original, 0, 0, width, height);
155                         graphics.Dispose();
156                 }
157
158                 public Bitmap (int width, int height, int stride, PixelFormat format, IntPtr scan0)
159                 {               
160                         IntPtr bmp;
161                                 
162                         Status status = GDIPlus.GdipCreateBitmapFromScan0 (width, height, stride, format, scan0, out bmp);
163                         GDIPlus.CheckStatus (status);   
164                         nativeObject = bmp;                                                                                                             
165                 }
166
167                 private Bitmap (SerializationInfo info, StreamingContext context)
168                         : base (info, context)
169                 {
170                 }
171
172                 #endregion
173                 // methods
174                 public Color GetPixel (int x, int y) {
175                         
176                         int argb;                               
177                         
178                         Status s = GDIPlus.GdipBitmapGetPixel(nativeObject, x, y, out argb);
179                         GDIPlus.CheckStatus (s);
180
181                         return Color.FromArgb(argb);            
182                 }
183
184                 public void SetPixel (int x, int y, Color color)
185                 {
186                         Status s = GDIPlus.GdipBitmapSetPixel (nativeObject, x, y, color.ToArgb ());
187                         if (s == Status.InvalidParameter) {
188                                 // check is done in case of an error only to avoid another
189                                 // unmanaged call for normal (successful) calls
190                                 if ((this.PixelFormat & PixelFormat.Indexed) != 0) {
191                                         string msg = Locale.GetText ("SetPixel cannot be called on indexed bitmaps.");
192 #if NET_2_0
193                                         throw new InvalidOperationException (msg);
194 #else
195                                         throw new Exception (msg);
196 #endif
197                                 }
198                         }
199                         GDIPlus.CheckStatus (s);
200                 }
201
202                 public Bitmap Clone (Rectangle rect, PixelFormat format)
203                 {                               
204                         IntPtr bmp;                     
205                         Status status = GDIPlus.GdipCloneBitmapAreaI (rect.X, rect.Y, rect.Width, rect.Height,
206                                 format, nativeObject, out bmp);
207                         GDIPlus.CheckStatus (status);
208                         return new Bitmap (bmp);
209                 }
210                 
211                 public Bitmap Clone (RectangleF rect, PixelFormat format)
212                 {
213                         IntPtr bmp;                     
214                         Status status = GDIPlus.GdipCloneBitmapArea (rect.X, rect.Y, rect.Width, rect.Height,
215                                 format, nativeObject, out bmp);
216                         GDIPlus.CheckStatus (status);
217                         return new Bitmap (bmp);
218                 }
219
220                 public static Bitmap FromHicon (IntPtr hicon)
221                 {       
222                         IntPtr bitmap;  
223                         Status status = GDIPlus.GdipCreateBitmapFromHICON (hicon, out bitmap);
224                         GDIPlus.CheckStatus (status);
225                         return new Bitmap (bitmap);
226                 }
227
228                 public static Bitmap FromResource (IntPtr hinstance, string bitmapName) //TODO: Untested
229                 {
230                         IntPtr bitmap;  
231                         Status status = GDIPlus.GdipCreateBitmapFromResource (hinstance, bitmapName, out bitmap);
232                         GDIPlus.CheckStatus (status);
233                         return new Bitmap (bitmap);
234                 }
235
236                 [EditorBrowsable (EditorBrowsableState.Advanced)]
237                 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
238                 public IntPtr GetHbitmap ()
239                 {
240                         return GetHbitmap(Color.Gray);
241                 }
242
243                 [EditorBrowsable (EditorBrowsableState.Advanced)]
244                 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
245                 public IntPtr GetHbitmap (Color background)
246                 {
247                         IntPtr HandleBmp;
248                         
249                         Status status = GDIPlus.GdipCreateHBITMAPFromBitmap (nativeObject, out HandleBmp, background.ToArgb ());
250                         GDIPlus.CheckStatus (status);
251
252                         return  HandleBmp;
253                 }
254
255                 [EditorBrowsable (EditorBrowsableState.Advanced)]
256                 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
257                 public IntPtr GetHicon ()
258                 {
259                         IntPtr HandleIcon;
260                         
261                         Status status = GDIPlus.GdipCreateHICONFromBitmap (nativeObject, out HandleIcon);
262                         GDIPlus.CheckStatus (status);
263
264                         return  HandleIcon;                     
265                 }
266
267                 public BitmapData LockBits (Rectangle rect, ImageLockMode flags, PixelFormat format)
268                 {
269                         BitmapData result = new BitmapData();
270                         return LockBits (rect, flags, format, result);
271                 }
272
273 #if NET_2_0
274                 public
275 #endif
276                 BitmapData LockBits (Rectangle rect, ImageLockMode flags, PixelFormat format, BitmapData bitmapData)
277                 {
278                         Status status = GDIPlus.GdipBitmapLockBits (nativeObject, ref rect, flags, format, bitmapData);
279                         //NOTE: scan0 points to piece of memory allocated in the unmanaged space
280                         GDIPlus.CheckStatus (status);
281
282                         return bitmapData;
283                 }
284
285                 public void MakeTransparent ()
286                 {
287                         Color clr = GetPixel(0,0);                      
288                         MakeTransparent (clr);
289                 }
290
291                 public void MakeTransparent (Color transparentColor)
292                 {                                                       
293                         // We have to draw always over a 32-bitmap surface that supports alpha channel
294                         Bitmap  bmp = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
295                         Graphics gr = Graphics.FromImage(bmp);
296                         Rectangle destRect = new Rectangle(0, 0, Width, Height);
297                         ImageAttributes imageAttr = new ImageAttributes();
298                         
299                         imageAttr.SetColorKey(transparentColor, transparentColor);
300
301                         gr.DrawImage (this, destRect, 0, 0, Width, Height, GraphicsUnit.Pixel, imageAttr);                                      
302                         
303                         IntPtr oldBmp = nativeObject;
304                         nativeObject = bmp.nativeObject;
305                         bmp.nativeObject = oldBmp;
306
307                         gr.Dispose();
308                         bmp.Dispose();
309                         imageAttr.Dispose();
310                 }
311
312                 public void SetResolution (float xDpi, float yDpi)
313                 {
314                         Status status = GDIPlus.GdipBitmapSetResolution (nativeObject, xDpi, yDpi);
315                         GDIPlus.CheckStatus (status);
316                 }
317
318                 public void UnlockBits (BitmapData bitmapdata)
319                 {
320                         Status status = GDIPlus.GdipBitmapUnlockBits (nativeObject, bitmapdata);
321                         GDIPlus.CheckStatus (status);
322                 }
323         }
324 }