UnmanagedBitmap.cs
5.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace eyemLib_Sharp
{
public unsafe class UnmanagedBitmap : IDisposable
{
private EyemImage image;
public EyemImage Image
{
get { return image; }
}
/// <summary>
/// 初始化新实例
/// </summary>
public UnmanagedBitmap()
{
image = new EyemImage();
}
/// <summary>
/// 从指定文件初始化UnmanagedBitmap的新实例(支持BMP、DIB、PNG、PBM、PGM、PPM、EXR、JPEG、JPG、JPE、TIF等格式图像)
/// </summary>
/// <param name="fileName">文件名</param>
public UnmanagedBitmap(string fileName)
{
eyemImageRead(fileName, -1, out image);
}
/// <summary>
/// 从Bitmap初始化Unmanaged新实例(GDI不支持除8位以外深度的图像;若要加载不同深度图像请使用从文件名加载)
/// </summary>
/// <param name="bitmap"></param>
public UnmanagedBitmap(Bitmap bitmap)
{
image = eyemCvtToEyemImage(bitmap);
}
/// <summary>
/// 隐式转换成EyemImage
/// </summary>
/// <param name="operand"></param>
public static implicit operator EyemImage(UnmanagedBitmap operand)
{
return operand.Image;
}
~UnmanagedBitmap()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// dispose managed resources
}
//这里特别修改了eyemCvtToEyemImage的内存分配,因此皆可以由此接口释放
eyemImageFree(ref image);
}
#region 接口
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemImageRead(string filename, int iFalgs, out EyemImage tpImage);
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern void eyemImageFree(ref EyemImage tpImage);
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemCvtImageType(EyemImage tpImage, string ccSubType, double alpha, double beta, ref EyemImage tpDstImg);
/// <summary>
/// 从进程中的非托管内存分配指定长度的内存
/// </summary>
/// <param name="cb">长度</param>
/// <returns>地址</returns>
[DllImport("eyemLib.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr eyemMallocMemBlock(int cb);
/// <summary>
/// 释放从非托管内存中分配的内存
/// </summary>
/// <param name="block">地址</param>
[DllImport("eyemLib.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void eyemFreeMemBlock(IntPtr block);
#endregion
#region EyemImage与Bitmap相互转换
public static EyemImage eyemCvtToEyemImage(Bitmap bitmap)
{
EyemImage tpImage = new EyemImage();
//锁定数据区
BitmapData bd = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly, bitmap.PixelFormat);
switch (bitmap.PixelFormat)
{
case PixelFormat.Format8bppIndexed:
tpImage.iChannels = 1;
break;
case PixelFormat.Format24bppRgb:
tpImage.iChannels = 3;
break;
case PixelFormat.Format32bppArgb:
tpImage.iChannels = 4;
break;
default:
throw new Exception("Image formats are not supported");
}
//仅支持8位
tpImage.iDepth = 0;
//图像尺寸
tpImage.iWidth = bitmap.Width; tpImage.iHeight = bitmap.Height;
//分配内存(此函数分配的内存可由默认接口释放)
tpImage.vpImage = eyemMallocMemBlock(bd.Stride * bd.Height);
try
{
int pd = ((tpImage.iWidth * tpImage.iChannels) + 3) / 4 * 4;
long bytesToCopy = tpImage.iWidth * tpImage.iChannels;
for (int y = 0; y < tpImage.iHeight; y++)
{
long offsetSrc = y * pd;
long offsetDst = y * tpImage.iWidth * tpImage.iChannels;
Buffer.MemoryCopy((byte*)(bd.Scan0.ToPointer()) + offsetSrc, (byte*)(tpImage.vpImage.ToPointer()) + offsetDst, bytesToCopy, bytesToCopy);
}
}
finally
{
bitmap.UnlockBits(bd);
}
return tpImage;
}
#endregion
}
}