131 lines
3.6 KiB
C#
131 lines
3.6 KiB
C#
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;
|
|
|
|
/// <summary>
|
|
/// Initializes a newinstance with the given image dimensions and pixel-data
|
|
/// </summary>
|
|
/// <param name="width">the image width in pixel</param>
|
|
/// <param name="height">the image height in pixel</param>
|
|
/// <param name="channels">the number of color channels (1-4)</param>
|
|
/// <param name="channelDepth">the bit-depth per channel (8 or 16)</param>
|
|
/// <param name="data">pointer to the pixel data in unmanaged memory</param>
|
|
/// <param name="step">the number of bytes per image row</param>
|
|
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;
|
|
}
|
|
}
|
|
} |