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)
Bitmap()56 		private Bitmap ()
57 		{
58 		}
59 
Bitmap(IntPtr ptr)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)
Bitmap(IntPtr ptr, Stream stream)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 
Bitmap(int width, int height)76 		public Bitmap (int width, int height) : this (width, height, PixelFormat.Format32bppArgb)
77 		{
78 		}
79 
Bitmap(int width, int height, Graphics g)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 
Bitmap(int width, int height, PixelFormat format)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 
Bitmap(Image original)100 		public Bitmap (Image original) : this (original, original.Width, original.Height) {}
101 
Bitmap(Stream stream)102 		public Bitmap (Stream stream)  : this (stream, false) {}
103 
Bitmap(string filename)104 		public Bitmap (string filename) : this (filename, false) {}
105 
Bitmap(Image original, Size newSize)106 		public Bitmap (Image original, Size newSize)  : this(original, newSize.Width, newSize.Height) {}
107 
Bitmap(Stream stream, bool useIcm)108 		public Bitmap (Stream stream, bool useIcm)
109 		{
110 			// false: stream is owned by user code
111 			nativeObject = InitFromStream (stream);
112 		}
113 
Bitmap(string filename, bool useIcm)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 
Bitmap(Type type, string resource)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 
Bitmap(Image original, int width, int height)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 
Bitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0)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 
Bitmap(SerializationInfo info, StreamingContext context)169 		private Bitmap (SerializationInfo info, StreamingContext context)
170 			: base (info, context)
171 		{
172 		}
173 
174 		#endregion
175 		// methods
GetPixel(int x, int y)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 
SetPixel(int x, int y, Color color)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 
Clone(Rectangle rect, PixelFormat format)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 
Clone(RectangleF rect, PixelFormat format)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 
FromHicon(IntPtr hicon)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 
FromResource(IntPtr hinstance, string bitmapName)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)]
GetHbitmap()235 		public IntPtr GetHbitmap ()
236 		{
237 			return GetHbitmap(Color.Gray);
238 		}
239 
240 		[EditorBrowsable (EditorBrowsableState.Advanced)]
GetHbitmap(Color background)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)]
GetHicon()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 
LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format)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
LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format, BitmapData bitmapData)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 
MakeTransparent()278 		public void MakeTransparent ()
279 		{
280 			Color clr = GetPixel(0,0);
281 			MakeTransparent (clr);
282 		}
283 
MakeTransparent(Color transparentColor)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 
SetResolution(float xDpi, float yDpi)305 		public void SetResolution (float xDpi, float yDpi)
306 		{
307 			Status status = GDIPlus.GdipBitmapSetResolution (nativeObject, xDpi, yDpi);
308 			GDIPlus.CheckStatus (status);
309 		}
310 
UnlockBits(BitmapData bitmapdata)311 		public void UnlockBits (BitmapData bitmapdata)
312 		{
313 			Status status = GDIPlus.GdipBitmapUnlockBits (nativeObject, bitmapdata);
314 			GDIPlus.CheckStatus (status);
315 		}
316 	}
317 }
318