2005-10-04 Zoltan Varga <vargaz@freemail.hu>
[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                 internal Bitmap (IntPtr ptr)
55                 {
56                         nativeObject = ptr;
57                 }
58
59                 public Bitmap (int width, int height) : this (width, height, PixelFormat.Format32bppArgb)
60                 {
61                         
62                 }
63
64                 public Bitmap (int width, int height, Graphics g)
65                 {               
66                         IntPtr bmp;
67                         Status s = GDIPlus.GdipCreateBitmapFromGraphics (width, height, g.nativeObject, out bmp);
68                         GDIPlus.CheckStatus (s);
69                         nativeObject = (IntPtr)bmp;                                             
70                 }
71
72                 public Bitmap (int width, int height, PixelFormat format)
73                 {       
74                         IntPtr bmp;
75                         Status s = GDIPlus.GdipCreateBitmapFromScan0 (width, height, 0, format, IntPtr.Zero, out bmp);
76                         GDIPlus.CheckStatus (s);
77                         nativeObject = (IntPtr) bmp;
78                         
79                 }
80
81                 public Bitmap (Image original) : this (original, original.Width, original.Height) {}
82
83                 public Bitmap (Stream stream)  : this (stream, false) {} 
84
85                 public Bitmap (string filename) : this (filename, false) {}
86
87                 public Bitmap (Image original, Size newSize)  : this(original, newSize.Width, newSize.Height) {}
88                 
89                 internal Bitmap (int width, int height, PixelFormat pixel, IntPtr bmp)
90                 {                       
91                         nativeObject = (IntPtr)bmp;                                             
92                 }
93                 
94                 internal Bitmap (float width, float height, PixelFormat pixel, IntPtr bmp)
95                 {                       
96                         nativeObject = (IntPtr)bmp;                     
97                         
98                 }
99
100                 public Bitmap (Stream stream, bool useIcm)
101                 {
102                         if (stream == null)
103                                 throw new ArgumentNullException ("stream");
104
105                         InitFromStream (stream);
106                 }
107
108                 public Bitmap (string filename, bool useIcm)
109                 {
110                         IntPtr imagePtr;
111                         Status st;
112
113                         if (useIcm)
114                                 st = GDIPlus.GdipCreateBitmapFromFileICM (filename, out imagePtr);
115                         else
116                                 st = GDIPlus.GdipCreateBitmapFromFile (filename, out imagePtr);
117
118                         GDIPlus.CheckStatus (st);
119                         nativeObject = imagePtr;
120                 }
121
122                 public Bitmap (Type type, string resource)
123                 {
124                         using (Stream s = type.Assembly.GetManifestResourceStream (type, resource)){
125                                 if (s == null)
126                                         throw new FileNotFoundException ("Resource name was not found: `" + resource + "'");
127
128                                 InitFromStream (s);
129                         }
130                 }
131
132                 public Bitmap (Image original, int width, int height)  : this(width, height, PixelFormat.Format32bppArgb)
133                 {
134                         Graphics graphics = Graphics.FromImage(this);
135
136                         graphics.DrawImage(original, 0, 0, width, height);
137                         graphics.Dispose();
138                 }
139
140                 public Bitmap (int width, int height, int stride, PixelFormat format, IntPtr scan0)
141                 {               
142                         IntPtr bmp;
143                                 
144                         Status status = GDIPlus.GdipCreateBitmapFromScan0 (width, height, stride, format, scan0, out bmp);
145                         GDIPlus.CheckStatus (status);   
146                         nativeObject = (IntPtr) bmp;                                                                                                            
147                 }
148
149                 private Bitmap (SerializationInfo info, StreamingContext context)
150                 {
151                         foreach (SerializationEntry serEnum in info) {
152                                 if (String.Compare(serEnum.Name, "Data", true) == 0) {
153                                         byte[] bytes = (byte[]) serEnum.Value;
154                 
155                                         if (bytes != null) {
156                                                 InitFromStream(new MemoryStream(bytes));
157                                         }
158                                 }
159                         }
160                 }
161                 //The below function is not required. Call should resolve to base
162                 //Moreover there is a problem with the declaration. Base class function
163                 //is not declared as protected to access in descendent class
164                 /*private Bitmap (SerializationInfo info, StreamingContext context) : base(info, context)
165                 {
166                 }*/
167
168                 #endregion
169                 // methods
170                 public Color GetPixel (int x, int y) {
171                         
172                         int argb;                               
173                         
174                         Status s = GDIPlus.GdipBitmapGetPixel(nativeObject, x, y, out argb);
175                         GDIPlus.CheckStatus (s);
176
177                         return Color.FromArgb(argb);            
178                 }
179
180                 public void SetPixel (int x, int y, Color color)
181                 {                                                                       
182                         Status s = GDIPlus.GdipBitmapSetPixel(nativeObject, x, y, color.ToArgb());
183                         GDIPlus.CheckStatus (s);
184                 }
185
186                 public Bitmap Clone (Rectangle rect,PixelFormat format)
187                 {                               
188                         IntPtr bmp;                     
189                         Status status = GDIPlus.GdipCloneBitmapAreaI(rect.X, rect.Top, rect.Width, rect.Height,
190                                PixelFormat, nativeObject,  out bmp);
191                                
192                         GDIPlus.CheckStatus (status);
193
194                         Bitmap bmpnew = new Bitmap (rect.Width, rect.Height,  PixelFormat, (IntPtr) bmp);
195                         return bmpnew;
196                 }
197                 
198                 public Bitmap Clone (RectangleF rect, PixelFormat format)
199                 {
200                         IntPtr bmp;                     
201                         Status status = GDIPlus.GdipCloneBitmapArea (rect.X, rect.Top, rect.Width, rect.Height,
202                                PixelFormat, nativeObject,  out bmp);
203                         GDIPlus.CheckStatus (status);
204
205                         Bitmap bmpnew = new Bitmap (rect.Width, rect.Height,  PixelFormat, (IntPtr) bmp);
206                         return bmpnew;
207                 }
208
209                 public static Bitmap FromHicon (IntPtr hicon)   //TODO: Untested
210                 {       
211                         IntPtr bitmap;  
212                                 
213                         Status status = GDIPlus.GdipCreateBitmapFromHICON (hicon, out bitmap);
214                         GDIPlus.CheckStatus (status);
215
216                         return new Bitmap (0,0, PixelFormat.Format32bppArgb, bitmap);   // FIXME
217                 }
218
219                 public static Bitmap FromResource (IntPtr hinstance, string bitmapName) //TODO: Untested
220                 {
221                         IntPtr bitmap;  
222                                 
223                         Status status = GDIPlus.GdipCreateBitmapFromResource (hinstance, bitmapName, out bitmap);
224                         GDIPlus.CheckStatus (status);
225
226                         return new Bitmap (0,0, PixelFormat.Format32bppArgb, bitmap); // FIXME
227                 }
228
229                 [EditorBrowsable (EditorBrowsableState.Advanced)]
230                 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
231                 public IntPtr GetHbitmap ()
232                 {
233                         return GetHbitmap(Color.Gray);
234                 }
235
236                 [EditorBrowsable (EditorBrowsableState.Advanced)]
237                 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
238                 public IntPtr GetHbitmap (Color background)
239                 {
240                         IntPtr HandleBmp;
241                         
242                         Status status = GDIPlus.GdipCreateHBITMAPFromBitmap (nativeObject, out HandleBmp, background.ToArgb ());
243                         GDIPlus.CheckStatus (status);
244
245                         return  HandleBmp;
246                 }
247
248                 [EditorBrowsable (EditorBrowsableState.Advanced)]
249                 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
250                 public IntPtr GetHicon ()
251                 {
252                         IntPtr HandleIcon;
253                         
254                         Status status = GDIPlus.GdipCreateHICONFromBitmap (nativeObject, out HandleIcon);
255                         GDIPlus.CheckStatus (status);
256
257                         return  HandleIcon;                     
258                 }
259
260                 public BitmapData LockBits (Rectangle rect, ImageLockMode flags, PixelFormat format)
261                 {
262                         BitmapData result = new BitmapData();
263
264                         if (nativeObject == (IntPtr) 0)
265                                 throw new Exception ("nativeObject is null");                   
266                         
267                         IntPtr lfBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(result));
268                         Marshal.StructureToPtr(result, lfBuffer, false);                                                
269                 
270                         Status status = GDIPlus.GdipBitmapLockBits (nativeObject, ref rect, flags, format,  lfBuffer);
271                         
272                         result = (BitmapData) Marshal.PtrToStructure(lfBuffer,  typeof(BitmapData));                                                                                    
273                         Marshal.FreeHGlobal (lfBuffer);                 
274                         //NOTE: scan0 points to piece of memory allocated in the unmanaged space
275                         GDIPlus.CheckStatus (status);
276
277                         return  result;
278                 }
279
280                 public void MakeTransparent ()
281                 {
282                         Color clr = GetPixel(0,0);                      
283                         MakeTransparent (clr);
284                 }
285
286                 public void MakeTransparent (Color transparentColor)
287                 {                                                       
288                         // We have to draw always over a 32-bitmap surface that supports alpha channel
289                         Bitmap  bmp = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
290                         Graphics gr = Graphics.FromImage(bmp);
291                         Rectangle destRect = new Rectangle(0, 0, Width, Height);
292                         ImageAttributes imageAttr = new ImageAttributes();
293                         
294                         imageAttr.SetColorKey(transparentColor, transparentColor);
295
296                         gr.DrawImage (this, destRect, 0, 0, Width, Height, GraphicsUnit.Pixel, imageAttr);                                      
297                         
298                         IntPtr oldBmp = nativeObject;
299                         nativeObject = bmp.nativeObject;
300                         bmp.nativeObject = oldBmp;
301
302                         gr.Dispose();
303                         bmp.Dispose();
304                         imageAttr.Dispose();
305                 }
306
307                 public void SetResolution (float xDpi, float yDpi)
308                 {
309                         Status status = GDIPlus.GdipBitmapSetResolution (nativeObject, xDpi, yDpi);
310                         GDIPlus.CheckStatus (status);
311                 }
312
313                 public void UnlockBits (BitmapData bitmap_data)
314                 {
315                         Status status = GDIPlus.GdipBitmapUnlockBits (nativeObject, bitmap_data);
316                         GDIPlus.CheckStatus (status);
317                 }
318         }
319 }