/// <summary> /// Clears the given bitmap with the given color /// </summary> /// <param name="bitmap">The bitmap to clear</param> /// <param name="color">The color to clear the bitmap with</param> public static void ClearBitmap(Bitmap bitmap, int color) { using (var fb = bitmap.FastLock()) { fb.Clear(color); } }
/// <summary> /// Copies a region of the source bitmap to a target bitmap /// </summary> /// <param name="source">The source image to copy</param> /// <param name="target">The target image to be altered</param> /// <param name="srcRect">The region on the source bitmap that will be copied over</param> /// <param name="destRect">The region on the target bitmap that will be changed</param> /// <exception cref="ArgumentException">The provided source and target bitmaps are the same bitmap</exception> public static void CopyRegion(Bitmap source, Bitmap target, Rectangle srcRect, Rectangle destRect) { var srcBitmapRect = new Rectangle(0, 0, source.Width, source.Height); var destBitmapRect = new Rectangle(0, 0, target.Width, target.Height); // If the copy operation results in an entire copy, use CopyPixels instead if (srcBitmapRect == srcRect && destBitmapRect == destRect && srcBitmapRect == destBitmapRect) { CopyPixels(source, target); return; } using (var fastTarget = target.FastLock()) { fastTarget.CopyRegion(source, srcRect, destRect); } }
/// <summary> /// Performs a copy operation of the pixels from the Source bitmap to the Target bitmap. /// If the dimensions or pixel depths of both images don't match, the copy is not performed /// </summary> /// <param name="source">The bitmap to copy the pixels from</param> /// <param name="target">The bitmap to copy the pixels to</param> /// <returns>Whether the copy proceedure was successful</returns> /// <exception cref="ArgumentException">The provided source and target bitmaps are the same</exception> public static bool CopyPixels(Bitmap source, Bitmap target) { if (source == target) { throw new ArgumentException(@"Copying pixels across the same bitmap is not supported", nameof(source)); } if (source.Width != target.Width || source.Height != target.Height || source.PixelFormat != target.PixelFormat) { return(false); } using (FastBitmap fastSource = source.FastLock(), fastTarget = target.FastLock()) { memcpy(fastTarget.Scan0, fastSource.Scan0, (ulong)(fastSource.Height * fastSource.Stride * BytesPerPixel)); } return(true); }
private void captureTarget() { int runX = x; int runY = y; Size runSize = new Size(width, height); while (this.running) { try { using (Bitmap screen = new Bitmap(runSize.Width, runSize.Height, PixelFormat.Format32bppArgb)) { using (Graphics grphx = Graphics.FromImage(screen)) { try { grphx.CopyFromScreen(runX, runY, 0, 0, runSize, CopyPixelOperation.SourceCopy); grphx.Save(); if (null != screen && NewScreenAvailEvent != null) { NewScreenAvailEvent(screen.FastLock().DataArray, EventArgs.Empty); } } catch (Exception e) { Log(e.Message + '\t' + e.StackTrace); } Thread.Sleep(captureThrottle); } } } catch (Exception ex) { Log(ex.Message + '\t' + ex.StackTrace); } } }
/// <summary> /// Copies a region of the source bitmap into this fast bitmap /// </summary> /// <param name="source">The source image to copy</param> /// <param name="srcRect">The region on the source bitmap that will be copied over</param> /// <param name="destRect">The region on this fast bitmap that will be changed</param> /// <exception cref="ArgumentException">The provided source bitmap is the same bitmap locked in this FastBitmap</exception> public void CopyRegion(Bitmap source, Rectangle srcRect, Rectangle destRect) { // Throw exception when trying to copy same bitmap over if (source == _bitmap) { throw new ArgumentException(@"Copying regions across the same bitmap is not supported", nameof(source)); } var srcBitmapRect = new Rectangle(0, 0, source.Width, source.Height); var destBitmapRect = new Rectangle(0, 0, Width, Height); // Check if the rectangle configuration doesn't generate invalid states or does not affect the target image if (srcRect.Width <= 0 || srcRect.Height <= 0 || destRect.Width <= 0 || destRect.Height <= 0 || !srcBitmapRect.IntersectsWith(srcRect) || !destRect.IntersectsWith(destBitmapRect)) { return; } // Find the areas of the first and second bitmaps that are going to be affected srcBitmapRect = Rectangle.Intersect(srcRect, srcBitmapRect); // Clip the source rectangle on top of the destination rectangle in a way that clips out the regions of the original bitmap // that will not be drawn on the destination bitmap for being out of bounds srcBitmapRect = Rectangle.Intersect(srcBitmapRect, new Rectangle(srcRect.X, srcRect.Y, destRect.Width, destRect.Height)); destBitmapRect = Rectangle.Intersect(destRect, destBitmapRect); // Clip the source bitmap region yet again here srcBitmapRect = Rectangle.Intersect(srcBitmapRect, new Rectangle(-destRect.X + srcRect.X, -destRect.Y + srcRect.Y, Width, Height)); // Calculate the rectangle containing the maximum possible area that is supposed to be affected by the copy region operation int copyWidth = Math.Min(srcBitmapRect.Width, destBitmapRect.Width); int copyHeight = Math.Min(srcBitmapRect.Height, destBitmapRect.Height); if (copyWidth == 0 || copyHeight == 0) { return; } int srcStartX = srcBitmapRect.Left; int srcStartY = srcBitmapRect.Top; int destStartX = destBitmapRect.Left; int destStartY = destBitmapRect.Top; using (var fastSource = source.FastLock()) { ulong strideWidth = (ulong)copyWidth * BytesPerPixel; // Perform copies of whole pixel rows for (int y = 0; y < copyHeight; y++) { int destX = destStartX; int destY = destStartY + y; int srcX = srcStartX; int srcY = srcStartY + y; long offsetSrc = (srcX + srcY * fastSource.Stride); long offsetDest = (destX + destY * Stride); memcpy(_scan0 + offsetDest, fastSource._scan0 + offsetSrc, strideWidth); } } }
/// <summary> /// Performs a copy operation of the pixels from the Source bitmap to the Target bitmap. /// If the dimensions or pixel depths of both images don't match, the copy is not performed /// </summary> /// <param name="source">The bitmap to copy the pixels from</param> /// <param name="target">The bitmap to copy the pixels to</param> /// <returns>Whether the copy proceedure was successful</returns> public static bool CopyPixels(Bitmap source, Bitmap target) { if (source.Width != target.Width || source.Height != target.Height || source.PixelFormat != target.PixelFormat) return false; using (FastBitmap fastSource = source.FastLock(), fastTarget = target.FastLock()) { memcpy(fastTarget.Scan0, fastSource.Scan0, (ulong)(fastSource.Height * fastSource._strideWidth * BytesPerPixel)); } return true; }
/// <summary> /// Copies a region of the source bitmap into this fast bitmap /// </summary> /// <param name="source">The source image to copy</param> /// <param name="srcRect">The region on the source bitmap that will be copied over</param> /// <param name="destRect">The region on this fast bitmap that will be changed</param> /// <exception cref="ArgumentException">The provided source bitmap is the same bitmap locked in this FastBitmap</exception> public void CopyRegion(Bitmap source, Rectangle srcRect, Rectangle destRect) { // Throw exception when trying to copy same bitmap over if (source == _bitmap) { throw new ArgumentException("Copying regions across the same bitmap is not supported", "source"); } Rectangle srcBitmapRect = new Rectangle(0, 0, source.Width, source.Height); Rectangle destBitmapRect = new Rectangle(0, 0, _width, _height); // Check if the rectangle configuration doesn't generate invalid states or does not affect the target image if (srcRect.Width <= 0 || srcRect.Height <= 0 || destRect.Width <= 0 || destRect.Height <= 0 || !srcBitmapRect.IntersectsWith(srcRect) || !destRect.IntersectsWith(destBitmapRect)) return; // Find the areas of the first and second bitmaps that are going to be affected srcBitmapRect = Rectangle.Intersect(srcRect, srcBitmapRect); // Clip the source rectangle on top of the destination rectangle in a way that clips out the regions of the original bitmap // that will not be drawn on the destination bitmap for being out of bounds srcBitmapRect = Rectangle.Intersect(srcBitmapRect, new Rectangle(srcRect.X, srcRect.Y, destRect.Width, destRect.Height)); destBitmapRect = Rectangle.Intersect(destRect, destBitmapRect); // Clipt the source bitmap region yet again here srcBitmapRect = Rectangle.Intersect(srcBitmapRect, new Rectangle(-destRect.X + srcRect.X, -destRect.Y + srcRect.Y, _width, _height)); // Calculate the rectangle containing the maximum possible area that is supposed to be affected by the copy region operation int copyWidth = Math.Min(srcBitmapRect.Width, destBitmapRect.Width); int copyHeight = Math.Min(srcBitmapRect.Height, destBitmapRect.Height); if (copyWidth == 0 || copyHeight == 0) return; int srcStartX = srcBitmapRect.Left; int srcStartY = srcBitmapRect.Top; int destStartX = destBitmapRect.Left; int destStartY = destBitmapRect.Top; using (FastBitmap fastSource = source.FastLock()) { ulong strideWidth = (ulong)copyWidth * BytesPerPixel; for (int y = 0; y < copyHeight; y++) { int destX = destStartX; int destY = destStartY + y; int srcX = srcStartX; int srcY = srcStartY + y; long offsetSrc = (srcX + srcY * fastSource._strideWidth); long offsetDest = (destX + destY * _strideWidth); memcpy(_scan0 + offsetDest, fastSource._scan0 + offsetSrc, strideWidth); } } }
public void TestCopyFromArrayMismatchedLengthException() { Bitmap bitmap = new Bitmap(4, 4); FillBitmapRegion(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height), Color.Red); int[] colors = { 0xFFFFFF, 0xFFFFEF, 0xABABAB, 0xABCDEF, 0x111111, 0x123456, 0x654321, 0x000000, 0x000000, 0xFFFFEF, 0x000000, 0xABCDEF, 0x000000, 0x000000, 0x654321, 0x000000, 0x000000, 0x000000, 0x654321, 0x000000 }; using (var fastBitmap = bitmap.FastLock()) { fastBitmap.CopyFromArray(colors, true); } }
public void TestCopyFromArrayIgnoreZeroes() { Bitmap bitmap = new Bitmap(4, 4); FillBitmapRegion(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height), Color.Red); int[] colors = { 0xFFFFFF, 0xFFFFEF, 0xABABAB, 0xABCDEF, 0x111111, 0x123456, 0x654321, 0x000000, 0x000000, 0xFFFFEF, 0x000000, 0xABCDEF, 0x000000, 0x000000, 0x654321, 0x000000 }; using (var fastBitmap = bitmap.FastLock()) { fastBitmap.CopyFromArray(colors, true); } // Test now the resulting bitmap for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { int index = y * bitmap.Width + x; int arrayColor = colors[index]; int bitmapColor = bitmap.GetPixel(x, y).ToArgb(); if(arrayColor != 0) { Assert.AreEqual(arrayColor, bitmapColor, "After a call to CopyFromArray(_, true), the non-zeroes values provided on the on the array must match the values in the bitmap pixels"); } else { Assert.AreEqual(Color.Red.ToArgb(), bitmapColor, "After a call to CopyFromArray(_, true), the 0 values on the original array must not be copied over"); } } } }
public void TestCopyFromArray() { Bitmap bitmap = new Bitmap(4, 4); int[] colors = { 0xFFFFFF, 0xFFFFEF, 0xABABAB, 0xABCDEF, 0x111111, 0x123456, 0x654321, 0x000000, 0xFFFFFF, 0xFFFFEF, 0xABABAB, 0xABCDEF, 0x111111, 0x123456, 0x654321, 0x000000 }; using (var fastBitmap = bitmap.FastLock()) { fastBitmap.CopyFromArray(colors); } // Test now the resulting bitmap for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { int index = y * bitmap.Width + x; Assert.AreEqual(colors[index], bitmap.GetPixel(x, y).ToArgb(), "After a call to CopyFromArray, the values provided on the on the array must match the values in the bitmap pixels"); } } }
public void TestLockExtensionMethod() { Bitmap bitmap = new Bitmap(64, 64); using (FastBitmap fast = bitmap.FastLock()) { fast.SetPixel(0, 0, Color.Red); } // Test unlocking by trying to modify the bitmap bitmap.SetPixel(0, 0, Color.Blue); }