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