/// <summary> /// Creates an unmanaged image representation from the provided array and image width (un-flattens the array). /// <para>No data is copied.</para> /// </summary> /// <param name="rawImageArray">Raw-byte image data array to lock.</param> /// <param name="width"> /// Image width. /// <para>Data length and the provided width must produce an integer height.</para> /// </param> /// <returns>Unmanaged image.</returns> public static Image <TColor> Lock(byte[] rawImageArray, int width) { GCHandle handle = GCHandle.Alloc(rawImageArray, GCHandleType.Pinned); float height = (float)rawImageArray.Length / (width * ColorInfo.GetInfo <TColor>().Size); if (height != (int)height) { throw new ArgumentException("The calculated height is not integer. There is a mismatch between given width, the data length and the image pixel type."); } var image = new Image <TColor>(handle.AddrOfPinnedObject(), width, (int)height, ColorInfo.GetInfo <TColor>().Size *width, handle, x => ((GCHandle)x).Free()); return(image); }
/// <summary> /// Extracts the specified image channels. /// </summary> /// <typeparam name="TSrcColor">Source color type.</typeparam> /// <typeparam name="TDepth">Channel depth type.</typeparam> /// <param name="image">Image.</param> /// <param name="area">Working area.</param> /// <param name="channelIndices">Channel indicies to extract. If null, all channels are extracted.</param> /// <returns>Channel collection.</returns> public static unsafe Gray <TDepth>[][,] SplitChannels <TSrcColor, TDepth>(this TSrcColor[,] image, Rectangle area, params int[] channelIndices) where TSrcColor : struct, IColor <TDepth> where TDepth : struct { if (channelIndices == null || channelIndices.Length == 0) { channelIndices = Enumerable.Range(0, ColorInfo.GetInfo <TSrcColor>().ChannelCount).ToArray(); } var channels = new Gray <TDepth> [channelIndices.Length][, ]; for (int i = 0; i < channelIndices.Length; i++) { channels[i] = GetChannel <TSrcColor, TDepth>(image, area, channelIndices[i]); } return(channels); }
/// <summary> /// Converts the specified bitmap into the managed array. /// </summary> /// <typeparam name="TColor">Color type.</typeparam> /// <param name="bmpSource">Bitmap source.</param> /// <returns>Managed array.</returns> public static TColor[,] ToArray <TColor>(this BitmapSource bmpSource) where TColor : struct, IColor <byte> { if (bmpSource.Format.BitsPerPixel != ColorInfo.GetInfo <TColor>().Size * 8) { throw new NotSupportedException("Color size and bitmap-source pixel format must match."); } TColor[,] im = new TColor[bmpSource.PixelHeight, bmpSource.PixelWidth]; using (var uIm = im.Lock()) { bmpSource.CopyPixels(Int32Rect.Empty, uIm.ImageData, uIm.Stride * uIm.Height, uIm.Stride); } return(im); }
/// <summary> /// Creates an unmanaged image by pinning the provided array. /// <para>No data is copied.</para> /// </summary> /// <param name="array">Array to lock.</param> /// <returns>Unmanaged image.</returns> public static Image <TColor> Lock(TColor[,] array) { GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned); int width = array.GetLength(1); int height = array.GetLength(0); var image = new Image <TColor>(handle.AddrOfPinnedObject(), width, height, ColorInfo.GetInfo <TColor>().Size *width, handle, x => ((GCHandle)x).Free()); return(image); }
private Image() { this.ColorInfo = ColorInfo.GetInfo <TColor>(); //an early init is needed during deserialization }