0

There are a number of posts about this, but i still can't figure it out. I am rather new at this, so please be forgiving.

I display an image, then grab a new image, and try to display it. When the new image is displayed, it has remnants of the old image. I have tried Picture1.Image= null to no avail.

Is it an issue with managed memory? I suspect it has to do with how the memory is being managed, that somehow the code copies a new image over and old image in a way that leaves some data from the previous image.

Here is the code to display the data in scaled1 (from this helpful earlier post):

Edit: Code added showing processing of arrays that are plotted. The overlaying behavior stops if the arrays are cleared using the Array.Clear method. Perhaps when this is cleared up I can post a canonical snippet demonstrating the issue.

This resets the question as: Why do arrays need to be cleared when each value of the array is rewritten? How can the array retain information of previous values?

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();
Community
  • 1
  • 1
DanG
  • 306
  • 7
  • 15
  • 1
    Are we talking Windows Forms, and if so, is `Picture1` a `PictureBox`? – Matthew Haugen Jul 15 '14 at 01:22
  • Yes, this is Windows Forms and `Picture1` is a `PictureBox`. @Luaan might want to chime in, since he suggested the code snippet. – DanG Jul 15 '14 at 01:29
  • 1
    Okay, and when you say "it has remnants of the old image," what do you mean? – Matthew Haugen Jul 15 '14 at 03:10
  • It looks like two images overlaying each other. – DanG Jul 15 '14 at 06:35
  • So one is half-transparent on top of the other? – Matthew Haugen Jul 15 '14 at 06:43
  • It is hard to tell since these are scientific images, but it is clear that remnants of prior images are in the new image. – DanG Jul 15 '14 at 17:12
  • Why don't you use **System.Drawing.Graphics** methods for modifiying your image? – Matin Lotfaliee Jul 15 '14 at 18:21
  • I was wondering the same thing a Matin, there. Have you looked into that class, or even that library as a whole? There are some great tools. I think there're a couple times when `Marshal.Copy` is still necessary, but it's pretty infrequent unless performance is outrageously important. – Matthew Haugen Jul 15 '14 at 19:13
  • What's the format of the file? If it's multi-layered (like Targa, or even animated GIFs), some weird issues might crop up. Also, you might want to include the code used to build the `scaled1` array. Are you sure there's no other control that might still be having the old image? And of course, are you sure the two images *aren't* actually to blame for the "remnants"? Have you tried doing `Bitmap.Save` to save the bitmaps to disk? That might show if it's in the bitmap data or the way your controls are arranged on the form. – Luaan Jul 15 '14 at 20:04
  • @MatthewHaugen Based on what code the OP has shown so far (small scientific images, indexed grey-scale palette) I'd expect using `Graphics` wouldn't really help much. A different approach overall might (e.g. using DirectX and pixel shaders to show the changes in real-time before exporting; I assume the OP is after things like brightness / contrast adjustment, gamma correction... but I might be wrong), but that would be a bit different issue. – Luaan Jul 15 '14 at 20:10
  • 1
    @luaan you clearly have a better idea of what's going on here than I, so I'll let you be. But first, if we are talking about modifying brightness and contrast, that reminds me of a post from [Scott Hanselman's blog](http://www.hanselman.com/blog/NuGetPackageOfTheWeekImageProcessorLightweightImageManipulationInC.aspx) from a little while ago. I've never used the ImageProcessor library but it sounds like it might provide a good way for you to do this. The license is a tad restrictive, but you could look into it. – Matthew Haugen Jul 15 '14 at 20:16
  • I'll try @Luaan test of save to see if it's in the controls (good idea), and add code of how `scaled1` array is built---in a few hours... – DanG Jul 16 '14 at 18:28
  • @Luaan pointed me in the right direction. The answer lies in the image processing, not the plotting. I fixed it, but would still like to understand why the fix works. See edits above. – DanG Jul 17 '14 at 01:22

1 Answers1

0

Actually, you're not replacing all values in the arrays - your for cycles are wrong. You want them to look like this:

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

The difference (i++ vs ++i) is that your way, you're skipping the first and the last index. C# arrays start at 0, while you start at 1 (you increment the loop variable before you run the body for the first time).

Also, note that for performance reasons, it's very handy if you're going through the array like this:

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

The JIT compiler recognizes this and avoids bounds checks, because it knows there can never be an overflow. When you're doing a lot of work with arrays, this can give you a massive performance boost, even if you access multiple arrays through the same index (one of them will not have the checks, the others will - still saves a lot of work).

The default JIT isn't very smart about this (it has to be quite fast), so pretty much anything else will reintroduce the bounds check. If performance is a concern for you, you'd want to profile the code anyway, of course.

EDIT: Ah, my bad. Anyway, I believe your problem isn't having to clear the frameringXXX arrays, but rather, the sumsin and sumcos arrays - you're always adding to those, so you'd be adding to the value that was already there, rather than starting from zero again. So you need to reset those arrays to zeroes first (which is what Array.Clear does).

Luaan
  • 62,244
  • 7
  • 97
  • 116
  • according to posts such as [this](http://stackoverflow.com/questions/484462/difference-between-i-and-i-in-a-loop), there is no distinction in for loops for pre- or post-incrementing. I also checked, and `i=0` in the first increment, and it does go to the last value. – DanG Jul 17 '14 at 22:33
  • @DanG Oops. That's interesting. It does make sense, of course, but I'm quite sure that it made a difference in some language. Well, my bad :D – Luaan Jul 18 '14 at 07:08
  • Yes, the correct answer in is the EDIT: the problem was adding to the `sumsin` and `sumcos` without zeroing. Doh! So no deep and subtle answer here, just my inexperience :). ps - I do remember something like PL/I had an increment index at start or end of loop. – DanG Jul 18 '14 at 18:11