/// <summary> /// Clone the unmanaged images. /// </summary> /// /// <returns>Returns clone of the unmanaged image.</returns> /// /// <remarks><para>The method does complete cloning of the object.</para></remarks> /// public UnmanagedImage Clone() { // allocate memory for the image IntPtr newImageData = System.Runtime.InteropServices.Marshal.AllocHGlobal(stride * height); System.GC.AddMemoryPressure(stride * height); UnmanagedImage newImage = new UnmanagedImage(newImageData, width, height, stride, pixelFormat); newImage.mustBeDisposed = true; SystemTools.CopyUnmanagedMemory(newImageData, imageData, stride * height); return(newImage); }
public static Bitmap Clone(BitmapData sourceData) { // get source image size int width = sourceData.Width; int height = sourceData.Height; // create new image Bitmap destination = new Bitmap(width, height, sourceData.PixelFormat); // lock destination bitmap data BitmapData destinationData = destination.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, destination.PixelFormat); SystemTools.CopyUnmanagedMemory(destinationData.Scan0, sourceData.Scan0, height * sourceData.Stride); // unlock destination image destination.UnlockBits(destinationData); return(destination); }
/// <summary> /// Process the filter on the specified image. /// </summary> /// /// <param name="sourceData">Source image data.</param> /// <param name="destinationData">Destination image data.</param> /// protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData) { // validate rectangle Rectangle srcRect = rect; srcRect.Intersect(new Rectangle(0, 0, sourceData.Width, sourceData.Height)); int xmin = srcRect.Left; int ymin = srcRect.Top; int ymax = srcRect.Bottom - 1; int copyWidth = srcRect.Width; int srcStride = sourceData.Stride; int dstStride = destinationData.Stride; int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8; int copySize = copyWidth * pixelSize; // do the job byte *src = (byte *)sourceData.ImageData.ToPointer() + ymin * srcStride + xmin * pixelSize; byte *dst = (byte *)destinationData.ImageData.ToPointer(); if (rect.Top < 0) { dst -= dstStride * rect.Top; } if (rect.Left < 0) { dst -= pixelSize * rect.Left; } // for each line for (int y = ymin; y <= ymax; y++) { SystemTools.CopyUnmanagedMemory(dst, src, copySize); src += srcStride; dst += dstStride; } }
/// <summary> /// Create managed image from the unmanaged. /// </summary> /// /// <param name="makeCopy">Make a copy of the unmanaged image or not.</param> /// /// <returns>Returns managed copy of the unmanaged image.</returns> /// /// <remarks><para>If the <paramref name="makeCopy"/> is set to <see langword="true"/>, then the method /// creates a managed copy of the unmanaged image, so the managed image stays valid even when the unmanaged /// image gets disposed. However, setting this parameter to <see langword="false"/> creates a managed image which is /// just a wrapper around the unmanaged image. So if unmanaged image is disposed, the /// managed image becomes no longer valid and accessing it will generate an exception.</para></remarks> /// /// <exception cref="InvalidImagePropertiesException">The unmanaged image has some invalid properties, which results /// in failure of converting it to managed image. This may happen if user used the /// <see cref="UnmanagedImage(IntPtr, int, int, int, PixelFormat)"/> constructor specifying some /// invalid parameters.</exception> /// public Bitmap ToManagedImage(bool makeCopy) { Bitmap dstImage = null; try { if (!makeCopy) { dstImage = new Bitmap(width, height, stride, pixelFormat, imageData); if (pixelFormat == PixelFormat.Format8bppIndexed) { ImageHelper.SetGrayscalePalette(dstImage); } } else { // create new image of required format dstImage = (pixelFormat == PixelFormat.Format8bppIndexed) ? ImageHelper.CreateGrayscaleImage(width, height) : new Bitmap(width, height, pixelFormat); // lock destination bitmap data BitmapData dstData = dstImage.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, pixelFormat); int dstStride = dstData.Stride; int lineSize = Math.Min(stride, dstStride); unsafe { byte *dst = (byte *)dstData.Scan0.ToPointer(); byte *src = (byte *)imageData.ToPointer(); if (stride != dstStride) { // copy image for (int y = 0; y < height; y++) { SystemTools.CopyUnmanagedMemory(dst, src, lineSize); dst += dstStride; src += stride; } } else { SystemTools.CopyUnmanagedMemory(dst, src, stride * height); } } // unlock destination images dstImage.UnlockBits(dstData); } return(dstImage); } catch (Exception) { if (dstImage != null) { dstImage.Dispose(); } throw new Exception("The unmanaged image has some invalid properties, which results in failure of converting it to managed image."); } }
/// <summary> /// Allocate new image in unmanaged memory. /// </summary> /// /// <param name="width">Image width.</param> /// <param name="height">Image height.</param> /// <param name="pixelFormat">Image pixel format.</param> /// /// <returns>Return image allocated in unmanaged memory.</returns> /// /// <remarks><para>Allocate new image with specified attributes in unmanaged memory.</para> /// /// <para><note>The method supports only /// <see cref="System.Drawing.Imaging.PixelFormat">Format8bppIndexed</see>, /// <see cref="System.Drawing.Imaging.PixelFormat">Format16bppGrayScale</see>, /// <see cref="System.Drawing.Imaging.PixelFormat">Format24bppRgb</see>, /// <see cref="System.Drawing.Imaging.PixelFormat">Format32bppRgb</see>, /// <see cref="System.Drawing.Imaging.PixelFormat">Format32bppArgb</see>, /// <see cref="System.Drawing.Imaging.PixelFormat">Format32bppPArgb</see>, /// <see cref="System.Drawing.Imaging.PixelFormat">Format48bppRgb</see>, /// <see cref="System.Drawing.Imaging.PixelFormat">Format64bppArgb</see> and /// <see cref="System.Drawing.Imaging.PixelFormat">Format64bppPArgb</see> pixel formats. /// In the case if <see cref="System.Drawing.Imaging.PixelFormat">Format8bppIndexed</see> /// format is specified, pallete is not not created for the image (supposed that it is /// 8 bpp grayscale image). /// </note></para> /// </remarks> /// /// <exception cref="UnsupportedImageFormatException">Unsupported pixel format was specified.</exception> /// <exception cref="InvalidImagePropertiesException">Invalid image size was specified.</exception> /// public static UnmanagedImage Create(int width, int height, PixelFormat pixelFormat) { int bytesPerPixel = 0; // calculate bytes per pixel switch (pixelFormat) { case PixelFormat.Format8bppIndexed: bytesPerPixel = 1; break; case PixelFormat.Format16bppGrayScale: bytesPerPixel = 2; break; case PixelFormat.Format24bppRgb: bytesPerPixel = 3; break; case PixelFormat.Format32bppRgb: case PixelFormat.Format32bppArgb: case PixelFormat.Format32bppPArgb: bytesPerPixel = 4; break; case PixelFormat.Format48bppRgb: bytesPerPixel = 6; break; case PixelFormat.Format64bppArgb: case PixelFormat.Format64bppPArgb: bytesPerPixel = 8; break; default: throw new Exception("Can not create image with specified pixel format."); } // check image size if ((width <= 0) || (height <= 0)) { throw new Exception("Invalid image size specified."); } // calculate stride int stride = width * bytesPerPixel; if (stride % 4 != 0) { stride += (4 - (stride % 4)); } // allocate memory for the image IntPtr imageData = System.Runtime.InteropServices.Marshal.AllocHGlobal(stride * height); SystemTools.SetUnmanagedMemory(imageData, 0, stride * height); System.GC.AddMemoryPressure(stride * height); UnmanagedImage image = new UnmanagedImage(imageData, width, height, stride, pixelFormat); image.mustBeDisposed = true; return(image); }