/// <summary> /// Create unmanaged image from the specified managed image. /// </summary> /// /// <param name="imageData">Source locked image data.</param> /// /// <returns>Returns new unmanaged image, which is a copy of source managed image.</returns> /// /// <remarks><para>The method creates an exact copy of specified managed image, but allocated /// in unmanaged memory. This means that managed image may be unlocked right after call to this /// method.</para></remarks> /// /// <exception cref="UnsupportedImageFormatException">Unsupported pixel format of source image.</exception> /// public static UnmanagedImage FromManagedImage(BitmapData imageData) { PixelFormat pixelFormat = imageData.PixelFormat; // check source pixel format if ( (pixelFormat != PixelFormat.Format8bppIndexed) && (pixelFormat != PixelFormat.Format16bppGrayScale) && (pixelFormat != PixelFormat.Format24bppRgb) && (pixelFormat != PixelFormat.Format32bppRgb) && (pixelFormat != PixelFormat.Format32bppArgb) && (pixelFormat != PixelFormat.Format32bppPArgb) && (pixelFormat != PixelFormat.Format48bppRgb) && (pixelFormat != PixelFormat.Format64bppArgb) && (pixelFormat != PixelFormat.Format64bppPArgb)) { throw new UnsupportedImageFormatException("Unsupported pixel format of the source image."); } // allocate memory for the image IntPtr dstImageData = System.Runtime.InteropServices.Marshal.AllocHGlobal(imageData.Stride * imageData.Height); System.GC.AddMemoryPressure(imageData.Stride * imageData.Height); UnmanagedImage image = new UnmanagedImage(dstImageData, imageData.Width, imageData.Height, imageData.Stride, pixelFormat); SystemTools.CopyUnmanagedMemory(dstImageData, imageData.Scan0, imageData.Stride * imageData.Height); image.mustBeDisposed = true; return(image); }
/// <summary> /// Copy unmanaged image. /// </summary> /// /// <param name="destImage">Destination image to copy this image to.</param> /// /// <remarks><para>The method copies current unmanaged image to the specified image. /// Size and pixel format of the destination image must be exactly the same.</para></remarks> /// /// <exception cref="InvalidImagePropertiesException">Destination image has different size or pixel format.</exception> /// public void Copy(UnmanagedImage destImage) { if ( (width != destImage.width) || (height != destImage.height) || (pixelFormat != destImage.pixelFormat)) { throw new InvalidImagePropertiesException("Destination image has different size or pixel format."); } if (stride == destImage.stride) { // copy entire image SystemTools.CopyUnmanagedMemory(destImage.imageData, imageData, stride * height); } else { unsafe { int dstStride = destImage.stride; int copyLength = (stride < dstStride) ? stride : dstStride; byte *src = (byte *)imageData.ToPointer(); byte *dst = (byte *)destImage.imageData.ToPointer(); // copy line by line for (int i = 0; i < height; i++) { SystemTools.CopyUnmanagedMemory(dst, src, copyLength); dst += dstStride; src += stride; } } } }
/// <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); }
/// <summary> /// Clone image. /// </summary> /// /// <param name="sourceData">Source image data.</param> /// /// <returns>Clones image from source image data. The message does not clone pallete in the /// case if the source image has indexed pixel format.</returns> /// 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> /// Apply filter to an image in unmanaged memory. /// </summary> /// /// <param name="sourceImage">Source image in unmanaged memory to apply filter to.</param> /// <param name="destinationImage">Destination image in unmanaged memory to put result into.</param> /// /// <remarks><para>The method keeps the source image unchanged and puts result of image processing /// into destination image.</para> /// /// <para><note>The destination image must have the same width and height as source image. Also /// destination image must have pixel format, which is expected by particular filter (see /// <see cref="FormatTranslations"/> property for information about pixel format conversions).</note></para> /// </remarks> /// /// <exception cref="UnsupportedImageFormatException">Unsupported pixel format of the source image.</exception> /// <exception cref="InvalidImagePropertiesException">Incorrect destination pixel format.</exception> /// <exception cref="InvalidImagePropertiesException">Destination image has wrong width and/or height.</exception> /// public void Apply(UnmanagedImage sourceImage, UnmanagedImage destinationImage) { // check pixel format of the source image CheckSourceFormat(sourceImage.PixelFormat); // ensure destination image has correct format if (destinationImage.PixelFormat != sourceImage.PixelFormat) { throw new InvalidImagePropertiesException("Destination pixel format must be the same as pixel format of source image."); } // ensure destination image has correct size if ((destinationImage.Width != sourceImage.Width) || (destinationImage.Height != sourceImage.Height)) { throw new InvalidImagePropertiesException("Destination image must have the same width and height as source image."); } // usually stride will be the same for 2 images of the size size/format, // but since this a public a method and users may provide any evil, we to need check it int dstStride = destinationImage.Stride; int srcStride = sourceImage.Stride; int lineSize = Math.Min(srcStride, dstStride); unsafe { byte *dst = (byte *)destinationImage.ImageData.ToPointer(); byte *src = (byte *)sourceImage.ImageData.ToPointer(); // copy image for (int y = 0, height = sourceImage.Height; y < height; y++) { SystemTools.CopyUnmanagedMemory(dst, src, lineSize); dst += dstStride; src += srcStride; } } // process the filter ProcessFilter(destinationImage, new Rectangle(0, 0, destinationImage.Width, destinationImage.Height)); }
/// <summary> /// Apply filter to an image. /// </summary> /// /// <param name="imageData">Source image to apply filter to.</param> /// /// <returns>Returns filter's result obtained by applying the filter to /// the source image.</returns> /// /// <remarks>The filter accepts bitmap data as input and returns the result /// of image processing filter as new image. The source image data are kept /// unchanged.</remarks> /// /// <exception cref="UnsupportedImageFormatException">Unsupported pixel format of the source image.</exception> /// public Bitmap Apply(BitmapData imageData) { // destination image format PixelFormat dstPixelFormat = imageData.PixelFormat; // check pixel format of the source image CheckSourceFormat(dstPixelFormat); // get image dimension int width = imageData.Width; int height = imageData.Height; // create new image of required format Bitmap dstImage = (dstPixelFormat == PixelFormat.Format8bppIndexed) ? AForgeImage.CreateGrayscaleImage(width, height) : new Bitmap(width, height, dstPixelFormat); // lock destination bitmap data BitmapData dstData = dstImage.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, dstPixelFormat); // copy image SystemTools.CopyUnmanagedMemory(dstData.Scan0, imageData.Scan0, imageData.Stride * height); try { // process the filter ProcessFilter(new UnmanagedImage(dstData), new Rectangle(0, 0, width, height)); } finally { // unlock destination images dstImage.UnlockBits(dstData); } return(dstImage); }
/// <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) { AForgeImage.SetGrayscalePalette(dstImage); } } else { // create new image of required format dstImage = (pixelFormat == PixelFormat.Format8bppIndexed) ? AForgeImage.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 InvalidImagePropertiesException("The unmanaged image has some invalid properties, which results in failure of converting it to managed image."); } }