新图像覆盖以前的位图

时间:2014-07-15 01:12:22

标签: c# bitmap system.drawing unmanaged-memory

有很多关于此的帖子,但我仍然无法弄明白。我对此很新,所以请原谅。

我显示图像,然后抓取一个新图像,并尝试显示它。显示新图像时,它具有旧图像的残余。我试过Picture1.Image= null无济于事。

托管内存是一个问题吗?我怀疑它与如何管理内存有关,不知何故,代码以一种从前一图像中留下一些数据的方式复制新图像和旧图像。

以下是在scaled1中显示数据的代码(来自this之前的帖子):

修改 添加的代码显示了绘制的数组的处理。如果使用Array.Clear方法清除数组,则覆盖行为将停止。也许当这个问题得到解决时,我可以发布一个证明该问题的规范片段。

这会将问题重置为:为什么在重写数组的每个值时都需要清除数组?数组如何保留先前值的信息?

ushort[] frame = null;
byte[] scaled1 = null;
double[][] frameringSin;
double[][] frameringCos;
double[] sumsin;
double[] sumcos;

frame = new ushort[mImageWidth * mImageHeight];
scaled1 = new byte[mImageWidth * mImageHeight];
frameringSin = new double[RingSize][];
frameringCos = new double[RingSize][];
ringsin = new double[RingSize];
ringcos = new double[RingSize];

//Fill array with images
for(int ring=0; ring <nN; ++ring)
                {
                    mCamera.GrabFrameReduced(framering[ring], reduced, out preset);
                }

//Process images
for (int i = 0; i < nN; ++i)
{
     Array.Clear(frameringSin[i], 0, frameringSin.Length);
     Array.Clear(frameringCos[i], 0, frameringSin.Length);
}
Array.Clear(sumsin, 0, sumsin.Length);
Array.Clear(sumcos, 0, sumcos.Length);
for(int r=0;r<nN; ++r)
{
     for (int i = 0; i < frame.Length; ++i)//upto 12 ms
     {
          frameringSin[r][i] = framering[r][i]* ringsin[r] / nN;
          frameringCos[r][i] = framering[r][i] *ringcos[r] / nN;
     }
}

for (int i = 0; i < sumsin.Length; ++i)//up to 25ms
{
    for (int r = 0; r < nN; ++r)
    {
        sumsin[i] += frameringSin[r][i];
        sumcos[i] += frameringCos[r][i];
    }
}

for(int r=0 ; r<nN ;++r)
{
    for (int i = 0; i < sumsin.Length; ++i)
    {
        A[i] = Math.Sqrt(sumsin[i] * sumsin[i] + sumcos[i] * sumcos[i]);
    }

//extract scaling parameters
...
//Scale Image
for (i1 = 0; i1 < frame.Length; ++i1)
    scaled1[i1] = (byte)((Math.Min(Math.Max(min1, frameA[i1]), max1) - min1) * scale1);


bmp1 = new Bitmap(mImageWidth,mImageHeight,System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
var bdata1 = bmp1.LockBits(new Rectangle(new Point(0, 0), bmp1.Size), ImageLockMode.WriteOnly, bmp1.PixelFormat);

 try
 {
      Marshal.Copy(scaled1, 0, bdata1.Scan0, scaled1.Length);
 }
 finally
 {
      bmp1.UnlockBits(bdata1);
 }

 Picture1.Image = bmp1;
 Picture1.Refresh();

1 个答案:

答案 0 :(得分:0)

实际上,您并没有替换数组中的所有值 - 您的for周期是错误的。你希望它们看起来像这样:

for (i1 = 0; i1 < frame.Length; i1++)
  scaled1[i1] = (byte)((Math.Min(Math.Max(min1, frameA[i1]), max1) - min1)
                       * scale1);

区别(i++ vs ++i)是您的方式,您正在跳过第一个和最后一个索引。 C#数组从0开始,而你从1开始(在第一次运行主体之前增加循环变量)。

此外,请注意,出于性能原因,如果您像这样通过数组,它会非常方便:

for (var i = 0; i < array.Length; i++)
  /* do work with array[i] */

JIT编译器识别这一点并避免边界检查,因为它知道永远不会有溢出。当您使用数组进行大量工作时,这可以为您提供巨大的性能提升,即使您通过相同的索引访问多个阵列(其中一个不会有检查,其他人将 - 仍然保存很多工作)。

默认的JIT对此并不是很聪明(它必须非常快),所以其他任何东西都会重新引入边界检查。如果性能是您的关注点,那么您当然希望对代码进行概要分析。

编辑:啊,我的坏。无论如何,我认为您的问题不是必须清除frameringXXX数组,而是sumsinsumcos数组 - 您总是会添加到这些数组,所以你要添加已经存在的值,而不是再从零开始。所以你需要先将这些数组重置为零(这是Array.Clear所做的)。