/// <summary> /// Initializes a new instance of the FastBitmapLocker struct with an initial fast bitmap object. /// The fast bitmap object passed will be unlocked after calling Dispose() on this struct /// </summary> /// <param name="fastBitmap">A fast bitmap to attach to this locker which will be released after a call to Dispose</param> public FastBitmapLocker(FastBitmap fastBitmap) { _fastBitmap = fastBitmap; }
/// <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); } } }