Merge pull request #4621 from alexanderkyte/strdup_env
[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.Reflection;
41 using System.Runtime.Serialization;
42 using System.Runtime.InteropServices;
43 using System.ComponentModel;
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                 // required for XmlSerializer (#323246)
56                 private Bitmap ()
57                 {
58                 }
59
60                 internal Bitmap (IntPtr ptr)
61                 {
62                         nativeObject = ptr;
63                 }
64
65                 // Usually called when cloning images that need to have
66                 // not only the handle saved, but also the underlying stream
67                 // (when using MS GDI+ and IStream we must ensure the stream stays alive for all the life of the Image)
68                 internal Bitmap(IntPtr ptr, Stream stream)
69                 {
70                         // under Win32 stream is owned by SD/GDI+ code
71                         if (GDIPlus.RunningOnWindows ())
72                                 this.stream = stream;
73                         nativeObject = ptr;
74                 }
75
76                 public Bitmap (int width, int height) : this (width, height, PixelFormat.Format32bppArgb)
77                 {
78                 }
79
80                 public Bitmap (int width, int height, Graphics g)
81                 {
82                         if (g == null)
83                                 throw new ArgumentNullException ("g");
84
85                         IntPtr bmp;
86                         Status s = GDIPlus.GdipCreateBitmapFromGraphics (width, height, g.nativeObject, out bmp);
87                         GDIPlus.CheckStatus (s);
88                         nativeObject = bmp;                                             
89                 }
90
91                 public Bitmap (int width, int height, PixelFormat format)
92                 {       
93                         IntPtr bmp;
94                         Status s = GDIPlus.GdipCreateBitmapFromScan0 (width, height, 0, format, IntPtr.Zero, out bmp);
95                         GDIPlus.CheckStatus (s);
96                         nativeObject = bmp;
97                         
98                 }
99
100                 public Bitmap (Image original) : this (original, original.Width, original.Height) {}
101
102                 public Bitmap (Stream stream)  : this (stream, false) {} 
103
104                 public Bitmap (string filename) : this (filename, false) {}
105
106                 public Bitmap (Image original, Size newSize)  : this(original, newSize.Width, newSize.Height) {}
107                 
108                 public Bitmap (Stream stream, bool useIcm)
109                 {
110                         // false: stream is owned by user code
111                         nativeObject = InitFromStream (stream);
112                 }
113
114                 public Bitmap (string filename, bool useIcm)
115                 {
116                         if (filename == null)
117                                 throw new ArgumentNullException ("filename");
118
119                         IntPtr imagePtr;
120                         Status st;
121
122                         if (useIcm)
123                                 st = GDIPlus.GdipCreateBitmapFromFileICM (filename, out imagePtr);
124                         else
125                                 st = GDIPlus.GdipCreateBitmapFromFile (filename, out imagePtr);
126
127                         GDIPlus.CheckStatus (st);
128                         nativeObject = imagePtr;
129                 }
130
131                 public Bitmap (Type type, string resource)
132                 {
133                         if (resource == null)
134                                 throw new ArgumentException ("resource");
135
136                         // For compatibility with the .NET Framework
137                         if (type == null)
138                                 throw new NullReferenceException();
139
140                         Stream s = type.GetTypeInfo ().Assembly.GetManifestResourceStream (type, resource);
141                         if (s == null) {
142                                 string msg = Locale.GetText ("Resource '{0}' was not found.", resource);
143                                 throw new FileNotFoundException (msg);
144                         }
145
146                         nativeObject = InitFromStream (s);
147                         // under Win32 stream is owned by SD/GDI+ code
148                         if (GDIPlus.RunningOnWindows ())
149                                 stream = s;
150                 }
151
152                 public Bitmap (Image original, int width, int height)  : this(width, height, PixelFormat.Format32bppArgb)
153                 {
154                         Graphics graphics = Graphics.FromImage(this);
155
156                         graphics.DrawImage(original, 0, 0, width, height);
157                         graphics.Dispose();
158                 }
159
160                 public Bitmap (int width, int height, int stride, PixelFormat format, IntPtr scan0)
161                 {               
162                         IntPtr bmp;
163                                 
164                         Status status = GDIPlus.GdipCreateBitmapFromScan0 (width, height, stride, format, scan0, out bmp);
165                         GDIPlus.CheckStatus (status);   
166                         nativeObject = bmp;                                                                                                             
167                 }
168
169                 private Bitmap (SerializationInfo info, StreamingContext context)
170                         : base (info, context)
171                 {
172                 }
173
174                 #endregion
175                 // methods
176                 public Color GetPixel (int x, int y) {
177                         
178                         int argb;                               
179                         
180                         Status s = GDIPlus.GdipBitmapGetPixel(nativeObject, x, y, out argb);
181                         GDIPlus.CheckStatus (s);
182
183                         return Color.FromArgb(argb);            
184                 }
185
186                 public void SetPixel (int x, int y, Color color)
187                 {
188                         Status s = GDIPlus.GdipBitmapSetPixel (nativeObject, x, y, color.ToArgb ());
189                         if (s == Status.InvalidParameter) {
190                                 // check is done in case of an error only to avoid another
191                                 // unmanaged call for normal (successful) calls
192                                 if ((this.PixelFormat & PixelFormat.Indexed) != 0) {
193                                         string msg = Locale.GetText ("SetPixel cannot be called on indexed bitmaps.");
194                                         throw new InvalidOperationException (msg);
195                                 }
196                         }
197                         GDIPlus.CheckStatus (s);
198                 }
199
200                 public Bitmap Clone (Rectangle rect, PixelFormat format)
201                 {                               
202                         IntPtr bmp;                     
203                         Status status = GDIPlus.GdipCloneBitmapAreaI (rect.X, rect.Y, rect.Width, rect.Height,
204                                 format, nativeObject, out bmp);
205                         GDIPlus.CheckStatus (status);
206                         return new Bitmap (bmp);
207                 }
208                 
209                 public Bitmap Clone (RectangleF rect, PixelFormat format)
210                 {
211                         IntPtr bmp;                     
212                         Status status = GDIPlus.GdipCloneBitmapArea (rect.X, rect.Y, rect.Width, rect.Height,
213                                 format, nativeObject, out bmp);
214                         GDIPlus.CheckStatus (status);
215                         return new Bitmap (bmp);
216                 }
217
218                 public static Bitmap FromHicon (IntPtr hicon)
219                 {       
220                         IntPtr bitmap;  
221                         Status status = GDIPlus.GdipCreateBitmapFromHICON (hicon, out bitmap);
222                         GDIPlus.CheckStatus (status);
223                         return new Bitmap (bitmap);
224                 }
225
226                 public static Bitmap FromResource (IntPtr hinstance, string bitmapName) //TODO: Untested
227                 {
228                         IntPtr bitmap;  
229                         Status status = GDIPlus.GdipCreateBitmapFromResource (hinstance, bitmapName, out bitmap);
230                         GDIPlus.CheckStatus (status);
231                         return new Bitmap (bitmap);
232                 }
233
234                 [EditorBrowsable (EditorBrowsableState.Advanced)]
235                 public IntPtr GetHbitmap ()
236                 {
237                         return GetHbitmap(Color.Gray);
238                 }
239
240                 [EditorBrowsable (EditorBrowsableState.Advanced)]
241                 public IntPtr GetHbitmap (Color background)
242                 {
243                         IntPtr HandleBmp;
244                         
245                         Status status = GDIPlus.GdipCreateHBITMAPFromBitmap (nativeObject, out HandleBmp, background.ToArgb ());
246                         GDIPlus.CheckStatus (status);
247
248                         return  HandleBmp;
249                 }
250
251                 [EditorBrowsable (EditorBrowsableState.Advanced)]
252                 public IntPtr GetHicon ()
253                 {
254                         IntPtr HandleIcon;
255                         
256                         Status status = GDIPlus.GdipCreateHICONFromBitmap (nativeObject, out HandleIcon);
257                         GDIPlus.CheckStatus (status);
258
259                         return  HandleIcon;                     
260                 }
261
262                 public BitmapData LockBits (Rectangle rect, ImageLockMode flags, PixelFormat format)
263                 {
264                         BitmapData result = new BitmapData();
265                         return LockBits (rect, flags, format, result);
266                 }
267
268                 public
269                 BitmapData LockBits (Rectangle rect, ImageLockMode flags, PixelFormat format, BitmapData bitmapData)
270                 {
271                         Status status = GDIPlus.GdipBitmapLockBits (nativeObject, ref rect, flags, format, bitmapData);
272                         //NOTE: scan0 points to piece of memory allocated in the unmanaged space
273                         GDIPlus.CheckStatus (status);
274
275                         return bitmapData;
276                 }
277
278                 public void MakeTransparent ()
279                 {
280                         Color clr = GetPixel(0,0);                      
281                         MakeTransparent (clr);
282                 }
283
284                 public void MakeTransparent (Color transparentColor)
285                 {                                                       
286                         // We have to draw always over a 32-bitmap surface that supports alpha channel
287                         Bitmap  bmp = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
288                         Graphics gr = Graphics.FromImage(bmp);
289                         Rectangle destRect = new Rectangle(0, 0, Width, Height);
290                         ImageAttributes imageAttr = new ImageAttributes();
291                         
292                         imageAttr.SetColorKey(transparentColor, transparentColor);
293
294                         gr.DrawImage (this, destRect, 0, 0, Width, Height, GraphicsUnit.Pixel, imageAttr);                                      
295                         
296                         IntPtr oldBmp = nativeObject;
297                         nativeObject = bmp.nativeObject;
298                         bmp.nativeObject = oldBmp;
299
300                         gr.Dispose();
301                         bmp.Dispose();
302                         imageAttr.Dispose();
303                 }
304
305                 public void SetResolution (float xDpi, float yDpi)
306                 {
307                         Status status = GDIPlus.GdipBitmapSetResolution (nativeObject, xDpi, yDpi);
308                         GDIPlus.CheckStatus (status);
309                 }
310
311                 public void UnlockBits (BitmapData bitmapdata)
312                 {
313                         Status status = GDIPlus.GdipBitmapUnlockBits (nativeObject, bitmapdata);
314                         GDIPlus.CheckStatus (status);
315                 }
316         }
317 }