/******************************************************************************
 * ScreenCapture.cs 
 * 
 * <Copyright and License> 
 * 
 * This file is part of GODS, a package for annotating medical images. 
 * 
 * Copyright (C) 2004 
 * Xuedong Chen 
 * Heri Mariwa 
 * Kimmy (Hsiang-ling) Lin 
 * Rui Yu 
 * 
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License 
 * as published by the Free Software Foundation; either version 2 
 * of the License, or (at your option) any later version. 
 * 
 * This program is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 *  
 * For further questions about this file, please send email to 
 * gods@cs.umb.edu or visit us at http://gods.sourceforge.net.  
 ******************************************************************************/

using System;
using System.Drawing;
using System.Drawing.Imaging;

namespace GODS
{
	namespace ScreenCapture
	{
		/// <summary>
		/// ScreenCapture class contains a set of methods that can capture the screen
		/// or a window with given window handler and return them as an Image object.
		/// </summary>
		public class ScreenCapture
		{
			/// <summary>
			/// Creates an Image object containing a screen shot of the entire desktop
			/// </summary>
			/// <returns></returns>
			public Image CaptureScreen() 
			{
				return CaptureWindow( User32.GetDesktopWindow() );
			}

			/// <summary>
			/// Creates an Image object containing a screen shot of a specific window
			/// </summary>
			/// <param name="handle">The handle to the window. (In windows forms, this is obtained by the Handle property)</param>
			/// <returns></returns>
			public Image CaptureWindow(IntPtr handle)
			{
				// get te hDC of the target window
				IntPtr hdcSrc = User32.GetWindowDC(handle);
				// get the size
				User32.RECT windowRect = new User32.RECT();
				User32.GetWindowRect(handle,ref windowRect);
				int width = windowRect.right - windowRect.left;
				int height = windowRect.bottom - windowRect.top;

				// create a device context we can copy to
				IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
				
				// create a bitmap we can copy it to,
				// using GetDeviceCaps to get the width/height
				IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc,width,height); 

				// select the bitmap object
				IntPtr hOld = GDI32.SelectObject(hdcDest,hBitmap);

				// bitblt over
				GDI32.BitBlt(hdcDest,0,0,width,height,hdcSrc,0,0,GDI32.SRCCOPY);

				// restore selection
				GDI32.SelectObject(hdcDest,hOld);
				// clean up 
				GDI32.DeleteDC(hdcDest);
				User32.ReleaseDC(handle,hdcSrc);
				// get a .NET image object for it
				Image img = Image.FromHbitmap(hBitmap);
				// free up the Bitmap object
				GDI32.DeleteObject(hBitmap);
				return this.adjustCapturedImageBrightness(img);
			}
			
			/// <summary>
			/// Due the internal screen capture makes the image much 
			/// brighter than original image.
			/// Thus we have to adjust the brighness of captured image
			/// Also the color is biased to red
			/// </summary>
			private Bitmap adjustCapturedImageBrightness(Image img)
			{
				float lumR = 0.3086f;
				float lumG = 0.6094f;
				float lumB = 0.0820f;
			
				float alpha = 1f;
				float brightness = -0.0923f;
				float brightnessRed=brightness, brightnessGreen=brightness+0.015f, brightnessBlue=brightness;
				float alphaRed = 0.0f,alphaGreen = 0.0f,alphaBlue=0.0f;
				float cw = 0f;
				float saturation = (float)10f/10f;
				float satCompl = 1.0f - saturation;
				float contrast = -0.05f;
				float conCompl = 0.1f*(1f-contrast);
	
				//metrix that used to adjust the color.
				//for details, please refer to color theory and Microsoft Library
				float[][] colorMatrixItems = {
												 new float[] {1*lumR*satCompl + saturation+contrast, -1f*cw + lumR*satCompl, -1f*cw + lumR*satCompl, 0, 0},
												 new float[] {cw+lumG*satCompl, 1*lumG*satCompl + saturation+contrast, -1f*cw + lumR*satCompl, 0, 0},
												 new float[] {cw+lumB*satCompl, cw+lumB*satCompl, 1*lumB*satCompl+saturation+contrast, 0, 0},
												 new float[] {alphaRed, alphaGreen, alphaBlue, alpha, 0},
												 new float[] {brightnessRed+conCompl, brightnessGreen+conCompl, brightnessBlue+conCompl, 0, 1}
											 };

				ColorMatrix colorMatrix = new ColorMatrix(colorMatrixItems);

				//Create an ImageAttributes class to contain a color matrix attribute
				ImageAttributes imAttr = new ImageAttributes();
				imAttr.SetColorMatrix(colorMatrix, 
					ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
				Bitmap bm = new Bitmap(img.Width,img.Height);
				Graphics g = Graphics.FromImage(bm);
				g.DrawImage(img,new Rectangle(0,0,bm.Width,bm.Height),
					0,0,bm.Width,bm.Height,GraphicsUnit.Pixel,imAttr);
				return bm;
			}
		}
	}
}

