static _Copy() { var dynamicMethod = new DynamicMethod ( "Copy", typeof(void), new[] { typeof(IntPtr), typeof(IntPtr), typeof(uint) }, typeof(_Copy) ); var ilGenerator = dynamicMethod.GetILGenerator(); ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldarg_1); ilGenerator.Emit(OpCodes.Ldarg_2); ilGenerator.Emit(OpCodes.Cpblk); ilGenerator.Emit(OpCodes.Ret); copy = (CopyFunc)dynamicMethod.CreateDelegate(typeof(CopyFunc)); }
static extern IntPtr g_boxed_type_register_static (IntPtr typename, CopyFunc copy_func, FreeFunc free_func);
static extern IntPtr g_boxed_type_register_static(IntPtr typename, CopyFunc copy_func, FreeFunc free_func);
/// <summary> /// Copys a rectangular block of pixel data from a source image to a destiation image (Blt = BlockTransfer). /// </summary> /// <param name="dst">The destination image.</param> /// <param name="xDst">The x destination coordinate (where to place the block within dst).</param> /// <param name="yDst">The y destination coordinate (where to place the block within dst).</param> /// <param name="src">The source image.</param> /// <param name="xSrc">The x source coordinate (where to start copying from within src).</param> /// <param name="ySrc">The y source coordinate (where to start copying from within src).</param> /// <param name="width">The width of the block to copy. (default is src.Width).</param> /// <param name="height">The height of the block to copy (default is src.Height).</param> /// <remarks> /// All specified parameters are clipped to avoid out-of-bounds indices. No warnings or exceptions are issued /// in case clipping results in a smaller or an empty block. /// </remarks> public static void Blt(ImageData dst, int xDst, int yDst, ImageData src, int xSrc = 0, int ySrc = 0, int width = 0, int height = 0) { if (width == 0) { width = src.Width; } if (height == 0) { height = src.Height; } ClipBlt(ref xDst, dst.Width, ref xSrc, src.Width, ref width); ClipBlt(ref yDst, dst.Height, ref ySrc, src.Height, ref height); if (width <= 0 || height <= 0) { return; } CopyFunc CopyLine = null; if (dst.PixelFormat == src.PixelFormat) { // We can copy an entire line en-bloc CopyLine = delegate(int idl, int isl) { Array.Copy(src.PixelData, isl + xSrc * src.BytesPerPixel, dst.PixelData, idl + xDst * dst.BytesPerPixel, width * dst.BytesPerPixel); }; } else { // Wee need to perform pixel-conversion while copying. CopyFunc CopyPixel = null; switch (dst.PixelFormat) { case ImagePixelFormat.RGBA: switch (src.PixelFormat) { case ImagePixelFormat.RGB: CopyPixel = delegate(int idp, int isp) { dst.PixelData[idp + 0] = src.PixelData[isp + 0]; dst.PixelData[idp + 1] = src.PixelData[isp + 1]; dst.PixelData[idp + 2] = src.PixelData[isp + 2]; dst.PixelData[idp + 3] = byte.MaxValue; }; break; case ImagePixelFormat.Intensity: CopyPixel = delegate(int idp, int isp) { dst.PixelData[idp + 0] = src.PixelData[isp]; dst.PixelData[idp + 1] = src.PixelData[isp]; dst.PixelData[idp + 2] = src.PixelData[isp]; dst.PixelData[idp + 3] = byte.MaxValue; }; break; default: throw new ArgumentOutOfRangeException(nameof(src), "Unknown source pixel format to copy to RGBA"); } break; case ImagePixelFormat.RGB: switch (src.PixelFormat) { case ImagePixelFormat.RGBA: CopyPixel = delegate(int idp, int isp) { dst.PixelData[idp + 0] = src.PixelData[isp + 0]; dst.PixelData[idp + 1] = src.PixelData[isp + 1]; dst.PixelData[idp + 2] = src.PixelData[isp + 2]; // skip source alpha src.PixelData[isp + 3]; }; break; case ImagePixelFormat.Intensity: CopyPixel = delegate(int idp, int isp) { dst.PixelData[idp + 0] = src.PixelData[isp]; dst.PixelData[idp + 1] = src.PixelData[isp]; dst.PixelData[idp + 2] = src.PixelData[isp]; }; break; default: throw new ArgumentOutOfRangeException(nameof(src), "Unknown source pixel format to copy to RGB"); } break; case ImagePixelFormat.Intensity: switch (src.PixelFormat) { case ImagePixelFormat.RGB: case ImagePixelFormat.RGBA: CopyPixel = delegate(int idp, int isp) { // Quick integer Luma conversion (not accurate) // See http://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color int R = src.PixelData[isp + 0]; int G = src.PixelData[isp + 1]; int B = src.PixelData[isp + 2]; dst.PixelData[idp] = (byte)((R + R + B + G + G + G) / 6); }; break; default: throw new ArgumentOutOfRangeException(nameof(src), "Unknown source pixel format to copy to RGB"); } break; default: throw new ArgumentOutOfRangeException(nameof(dst), "Unknown destination pixel format"); } CopyLine = delegate(int idl, int isl) { int iDstPxl = idl + xDst * dst.BytesPerPixel; int iSrcPxl = isl + xSrc * src.BytesPerPixel; for (int x = 0; x < width; x++) { CopyPixel(iDstPxl, iSrcPxl); iDstPxl += dst.BytesPerPixel; iSrcPxl += src.BytesPerPixel; } }; } int iDstLine = yDst * dst.Stride; int iSrcLine = ySrc * src.Stride; for (int y = 0; y < height; y++) { CopyLine(iDstLine, iSrcLine); iDstLine += dst.Stride; iSrcLine += src.Stride; } }