using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Runtime.InteropServices; namespace Inspectron.Camera.Image { public class ByteImage : IImage { Byte[] data; int step; /// /// Initializes a newinstance with the given image dimensions and pixel-data /// /// the image width in pixel /// the image height in pixel /// the number of color channels (1-4) /// the bit-depth per channel (8 or 16) /// pointer to the pixel data in unmanaged memory /// the number of bytes per image row public ByteImage(int width, int height, int channels, Byte[] data, int step) { Width = width; Height = height; Channels = channels; this.data = data; this.step = step; ProcessBitmapCache(); } private void ProcessBitmapCache() { var image = new Bitmap(Width, Height, Channels == 1 ? PixelFormat.Format8bppIndexed : PixelFormat.Format24bppRgb); var lockedDst = image.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, image.PixelFormat); Marshal.Copy(data, 0, lockedDst.Scan0, data.Length); image.UnlockBits(lockedDst); if (Channels == 1) { image.Palette = _monoPalette; } _cachedBMP = image; } static ColorPalette GetGrayScalePalette() { Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed); ColorPalette monoPalette = bmp.Palette; Color[] entries = monoPalette.Entries; for (int i = 0; i < 256; i++) { entries[i] = Color.FromArgb(i, i, i); } return monoPalette; } private static ColorPalette _monoPalette = GetGrayScalePalette(); public int Width { get; private set; } public int Height { get; private set; } public int Channels { get; private set; } public IImageLock Lock { get { return new ImageLock(this); } } private Bitmap _cachedBMP = null; public Bitmap Bitmap { get { return (Bitmap)_cachedBMP.Clone(); } } public byte[] Data { get => data; set => data = value; } public int Step { get => step; set => step = value; } class ImageLock : IImageLock { ByteImage parent; GCHandle pinnedArray; internal ImageLock(ByteImage parent) { this.parent = parent; } public int Step { get { return parent.step; } } public IntPtr PixelData { get { pinnedArray = GCHandle.Alloc(parent.data, GCHandleType.Pinned); IntPtr pointer = pinnedArray.AddrOfPinnedObject(); return pointer; } } public void Dispose() { pinnedArray.Free(); } } public void Save(string path) { (new Bitmap(new MemoryStream(data))).Save(path,ImageFormat.Bmp); } public void Dispose() { data = null; } } }