我写了一个程序,显示来自传感器的实时图像。问题在于它不断消耗记忆。
void tmr_Tick(object sender, EventArgs e)
{
object bpic = cam.GrabFrame();
uint[] pic = cam.ColorPipe(bpic, out width, out height, out bitdepth);
byte[] header = GetHeader.BuildHeader(width, height, bitdepth);
byte[] img = GetHeader.UintImageToByte(pic, width, height, bitdepth);
MemoryStream ms = new MemoryStream();
GC.Collect();
ms.Write(header, 0, header.Length);
ms.Write(img, 0, img.Length);
pictureBox1.Image.Dispose();
pictureBox1.Image = Image.FromStream(ms);
ms.Flush();
ms.Dispose();
}
}
class GetHeader
{
#region Image
public static byte[] UintImageToByte(uint[] img, uint nWidth, uint nHeight, uint nBitsPerPixel)
{
int nBytesPerPixel = (int)nBitsPerPixel / 8;
byte[] AoB = new byte[nWidth * nHeight * nBytesPerPixel];
int j = 0;
byte[] pixel;
// Get each uint value from image and convert it to bytes
for (int i = 0; i < img.Length; i++)
{
pixel = BitConverter.GetBytes(img[i]);
// Add each pixel bytes to the image array
for (int k = nBytesPerPixel - 1; k >= 0; k--)
{
AoB[j++] = pixel[k];
}
}
byte temp;
// Swap the elements to create a true color image
for (int i = 0; i < AoB.Length / 2; i++)
{
temp = AoB[i];
AoB[i] = AoB[AoB.Length - 1 - i];
AoB[AoB.Length - 1 - i] = temp;
}
return AoB;
}
#endregion
#region Header
/* IMPORTANT!!!!!
* All numerical values are little endian!
* 4660 in decimal will be 3421 in hex not 1234!
* IMPORTANT!!!!! */
private const uint HEADER_SIZE = 54;
private const string FOUR_BYTE_ZERO = "00000000";
private const string TWO_BYTE_ZERO = "0000";
private const string BM = "424D";
public static byte[] BuildHeader(uint nWidth, uint nHeight, uint nBitsPerPixel)
{
// Substring is to get the amount of bytes needed.
// BitConverter currently returns 4 bytes and in case it will change
// the substring will take the amount of bytes it needs.
string sWidth = BitConverter.ToString(BitConverter.GetBytes(nWidth)).Replace("-", "").Substring(0, 8);
string sHeight = BitConverter.ToString(BitConverter.GetBytes(nHeight)).Replace("-", "").Substring(0, 8);
string sBitsPerPixel = BitConverter.ToString(BitConverter.GetBytes(nBitsPerPixel)).Replace("-", "").Substring(0, 4);
uint nImageSize = ((nWidth * nHeight) * (nBitsPerPixel / 8));
string sFileSize = BitConverter.ToString(BitConverter.GetBytes(nImageSize + HEADER_SIZE)).Replace("-", "").Substring(0, 8);
string sImageSize = BitConverter.ToString(BitConverter.GetBytes(nImageSize)).Replace("-", "").Substring(0, 8);
string sHeader = String.Empty;
sHeader += BM; // 0h | File tpye | 2 bytes
sHeader += sFileSize; // 2h | File size | 4 bytes
sHeader += TWO_BYTE_ZERO; // 6h | N/A | 2 bytes
sHeader += TWO_BYTE_ZERO; // 8h | N/A | 2 bytes
sHeader += "36000000"; // Ah | Data offset | 4 bytes
sHeader += "28000000"; // Eh | DIB Size | 4 bytes
sHeader += sWidth; // 12h | Width | 4 bytes
sHeader += sHeight; // 16h | Height | 4 bytes
sHeader += "0100"; // 1Ah | Color planes | 2 bytes
sHeader += sBitsPerPixel; // 1Ch | Bits per pixel | 2 bytes
sHeader += FOUR_BYTE_ZERO; // 1Eh | Compression | 4 bytes
sHeader += sImageSize; // 22h | Image size | 4 bytes
sHeader += FOUR_BYTE_ZERO; // 26h | Horizontal res | 4 bytes
sHeader += FOUR_BYTE_ZERO; // 2Ah | Vertical res | 4 bytes
sHeader += FOUR_BYTE_ZERO; // 2Eh | Color pallete | 4 bytes
sHeader += FOUR_BYTE_ZERO; // 32h | Important colors | 4 bytes
byte[] Header = StringToAoB(sHeader);
return Header;
}
private static byte[] StringToAoB(string str)
{
byte[] AoB = new byte[str.Length / 2];
for (int i = 0, j = 0; i < AoB.Length; i++, j += 2)
{
AoB[i] = byte.Parse(HexToInt("0x" + str[j] + str[j + 1]).ToString());
}
return AoB;
}
private static int HexToInt(string Hex)
{
Hex = Hex.Replace("0x", "");
return Int32.Parse(Hex, System.Globalization.NumberStyles.AllowHexSpecifier);
}
#endregion
关键功能是tmr_Tick
和UintImageToByte
。
cam.GrabFrame()
返回包含原始图像数据的单维数组。
cam.ColorPipe()
将其排列为包含单维数组中每个像素的uint
表示。
我不知道问题似乎在哪里,如果它的内存没有从内存流中清除,或者间隔太快(200毫秒),gc可以标记未使用的内存并清理它。 / p>
如果有人花一些时间查看代码并就如何修复代码提出一些指示,我将不胜感激。
我试过using (MemoryStream ms....)
阻止无济于事。
ms.Flush()
,ms.Dispose()
和GC.Collect()
试图摆脱使用过的内存,但仍然没有。