/// <summary>
        /// Initializes the ScreenConfiguration for a collection of Screens
        /// with a specified BezelCompensation
        /// </summary>
        /// <param name="screens">Screens in the ScreenConfiguration</param>
        /// <param name="bezelCompensation">The BezelCompensation in pixels as an added margin to screen 
        /// bounds in a VirtualScreen to compensate for the display bezels in a multi-monitor setup</param>
        public ScreenConfiguration(Screen[] screens, int bezelCompensation)
        {
            this.screenDistributor = new ScreenDistributor(this);

            this.bezelCompensation = bezelCompensation; // private field so we don't trigger UpdateVirtualScreen() twice
            this.Screens = screens;
        }
        private void DrawScreenPerPixel(Bitmap wallpaper, Bitmap image, Screen screen)
        {
            Point screenPosition = new Point();
            Point imagePosition = new Point();
            Point wallpaperPosition = new Point();

            using (FastBitmap wallpaperBitmap = new FastBitmap(wallpaper))
            using (FastBitmap imageBitmap = new FastBitmap(image))
            {
                // Loop through all pixel rows
                for (screenPosition.Y = screen.Bounds.Y; screenPosition.Y <
                    screen.Bounds.Bottom; screenPosition.Y++)
                {
                    // Determine the vertical components of the image- and wallpaper positions
                    imagePosition.Y = screen.BoundsInVirtualScreen.Y + (screenPosition.Y - screen.Bounds.Y);
                    wallpaperPosition.Y = screenPosition.Y >= 0 ? screenPosition.Y : wallpaper.Height + screenPosition.Y;

                    // Loop through all pixels in the current row
                    for (screenPosition.X = screen.Bounds.X; screenPosition.X <
                        screen.Bounds.Right; screenPosition.X++)
                    {
                        // Determine the horizontal components of the image- and wallpaper positions
                        imagePosition.X = screen.BoundsInVirtualScreen.X + (screenPosition.X - screen.Bounds.X);
                        wallpaperPosition.X = screenPosition.X >= 0 ? screenPosition.X : wallpaper.Width + screenPosition.X;

                        // Assign the pixel data values at the image pixel position to the pixel at
                        // the wallpaper pixel position (copying it over)
                        FastBitmap.Pixel imagePixel = imageBitmap.GetPixel(imagePosition.X, imagePosition.Y);
                        wallpaperBitmap.SetPixel(wallpaperPosition.X, wallpaperPosition.Y, imagePixel);
                    }
                }
            }
        }
 private void DrawScreen(Bitmap wallpaper, Bitmap image, Screen screen)
 {
     if (screen.Bounds.X >= 0 && screen.Bounds.Y >= 0) // Needs optimization: doesn't cross x=0 or y=0
     {
         this.DrawScreenRectangle(wallpaper, image, screen);
     }
     else
     {
         this.DrawScreenPerPixel(wallpaper, image, screen);
     }
 }
        /// <summary>
        /// Determines the number of neighbor Screens on top
        /// </summary>
        /// <param name="screen">The Screen to determine the number of top neighbors for</param>
        /// <param name="offset">The offset of all screens in the ScreenConfiguration</param>
        /// <returns>The number of top neighbor Screen of the given Screen</returns>
        private int DetermineTopNeighborCount(Screen screen, Point offset)
        {
            Rectangle topNeighborRegion = new Rectangle(
                    screen.Bounds.X,
                    offset.Y,
                    screen.Bounds.Width,
                    screen.Bounds.Y - offset.Y);

            return this.screenConfiguration.Screens.Where(
                    s => s.Bounds.IntersectsWith(topNeighborRegion)).Count();
        }
        /// <summary>
        /// Determines the number of neighbor Screens on the left
        /// </summary>
        /// <param name="screen">The Screen to determine the number of neighbors on the left for</param>
        /// <param name="offset">The offset of all screens in the ScreenConfiguration</param>
        /// <returns>The number of neighbor Screens on the left of the given Screen</returns>
        private int DetermineLeftNeighborCount(Screen screen, Point offset)
        {
            Rectangle leftNeighborRegion = new Rectangle(
                    offset.X,
                    screen.Bounds.Y,
                    screen.Bounds.X - offset.X,
                    screen.Bounds.Height);

            return this.screenConfiguration.Screens.Where(
                    s => s.Bounds.IntersectsWith(leftNeighborRegion)).Count();
        }
        //private struct PixelData
        //{
        //    public byte blue;
        //    public byte green;
        //    public byte red;
        //    public byte alpha;
        //}
        //private void DrawScreenPerPixelFast(Bitmap wallpaper, Bitmap image, Screen screen)
        //{
        //    Point screenPosition = new Point();
        //    Point imagePosition = new Point();
        //    Point wallpaperPosition = new Point();
        //    BitmapData imageData = image.LockBits(screen.BoundsInImage, ImageLockMode.ReadOnly, image.PixelFormat);
        //    BitmapData wallpaperData = wallpaper.LockBits(new Rectangle(0, 0, wallpaper.Width, wallpaper.Height),
        //        ImageLockMode.WriteOnly, wallpaper.PixelFormat);
        //    unsafe
        //    {
        //        IntPtr imageDataOffset = imageData.Scan0;
        //        IntPtr wallpaperDataOffset = wallpaperData.Scan0;
        //        int wallpaperWidth = wallpaper.Width;
        //        int wallpaperHeight = wallpaper.Height;
        //        for (screenPosition.Y = screen.BoundsInSurface.Y; screenPosition.Y <
        //            screen.BoundsInSurface.Y + screen.BoundsInSurface.Height; screenPosition.Y++)
        //        {
        //            IntPtr imageYPosition = imageDataOffset + imagePosition.Y * imageData.Stride;
        //            wallpaperPosition.Y = screenPosition.Y >= 0 ?
        //                    screenPosition.Y : wallpaperHeight + screenPosition.Y;
        //            imagePosition.Y = screen.BoundsInImage.Y + (screenPosition.Y - screen.BoundsInSurface.Y);
        //            for (screenPosition.X = screen.BoundsInSurface.X; screenPosition.X <
        //                screen.BoundsInSurface.X + screen.BoundsInSurface.Width; screenPosition.X++)
        //            {
        //                // Positions in wallpaper (destination)
        //                wallpaperPosition.X = screenPosition.X >= 0 ?
        //                    screenPosition.X : wallpaperWidth + screenPosition.X;
        //                // Position in image (source) = BoundsInImage + offset
        //                imagePosition.X = screen.BoundsInImage.X + (screenPosition.X - screen.BoundsInSurface.X);
        //                PixelData imagePixel = *(PixelData*)(imageYPosition + imagePosition.X * sizeof(PixelData));
        //                PixelData* wallpaperPixel = (PixelData*)(wallpaperDataOffset + wallpaperPosition.Y * wallpaperData.Stride +
        //                    wallpaperPosition.X * sizeof(PixelData));
        //                *wallpaperPixel = imagePixel;
        //            }
        //        }
        //    }
        //    image.UnlockBits(imageData);
        //    wallpaper.UnlockBits(wallpaperData);
        //}
        private void DrawScreenRectangle(Bitmap wallpaper, Bitmap image, Screen screen)
        {
            System.Drawing.Rectangle destination = screen.Bounds;
            destination.X = destination.X >= 0 ? destination.X : wallpaper.Width + destination.X;
            destination.Y = destination.Y >= 0 ? destination.Y : wallpaper.Height + destination.Y;

            using (Graphics graphics = Graphics.FromImage(wallpaper))
            {
                graphics.DrawImage(image, destination, screen.BoundsInVirtualScreen, GraphicsUnit.Pixel);
            }
        }
 /// <summary>
 /// Initializes the ScreenConfiguration for a collection of Screens and
 /// a default BezelCompensation of 0
 /// </summary>
 /// <param name="screens">Screens in the ScreenConfiguration</param>
 public ScreenConfiguration(Screen[] screens)
     : this(screens, 0)
 {
 }