Re: image Clone problem when using LockBits
From: Norvin Laudon (nospamnorvinll_at_molinospamenergy.com)
Date: 04/02/04
- Next message: Tim Blanton: ".NET PictureBox vs VB6 PictureBox"
- Previous message: Bob Powell [MVP]: "Re: GraphicsPath help please"
- In reply to: Norvin Laudon: "Re: image Clone problem when using LockBits"
- Messages sorted by: [ date ] [ thread ]
Date: Fri, 2 Apr 2004 14:36:02 -0800
Hi Bob,
Unfortunately, I haven't made any progress with my video stream averaging
program. I'm going to try to redescribe this problem as simply as possible.
1. One thread of my program is constantly aquiring pictures from a frame
grabber. It creates 8bpp indexed Bitmap objects using a pointer to some
image data. As each frame is ready, it fires an "ImageReady" event. (see
code at bottom)
2. The averaging thread subscribes to the "ImageReady" event. As each frame
arrives, it clones it and adds it to an ArrayList object as follows:
<code>
imageQueue.Add((Bitmap)e.bitmap.Clone());
</code>
The problem is, when the next frame arrives, *all* images which are in the
ArrayList contain the same bit data as the new frame! Even though I use the
Clone() method when adding images to the ArrayList, these images are somehow
tied back to the original frame.
The following is the code that creates each image and fires the "ImageReady"
event:
<code>
int ptr = FrameBuffer(frh); // get a pointer to the image data
if (ptr==0)
{
throw new Exception("Fatal Frame Grabber Error: Grab failed.");
}
// use the pointer to create a bmp
Bitmap bmp = new Bitmap(640, 480, 640,
PixelFormat.Format8bppIndexed,
new System.IntPtr(ptr));
// use the greyscale palette
bmp.Palette = greyPal;
if (ImageReady != null) // if anyone has subscribed to this event, fire
it
ImageReady(this, new ImageReadyEventArgs(bmp));
</code>
Can anybody shed some light on this?
Thanks,
Norvin
"Norvin Laudon" <nospamnorvinll@molinospamenergy.com> wrote in message
news:eLqgvqEGEHA.3288@TK2MSFTNGP12.phx.gbl...
> Hi Bob,
>
> I getting close to the root of the problem. My frame grabber (unmanaged
dll)
> gives me a pointer to a frame buffer which contains some image data (8bpp,
> Indexed). I use one of the overloads of the Bitmap class (the one that
takes
> a pointer) to create a Bitmap object, then fire an event to pass it off to
> my other functions.
>
> I tweaked your simple test to simulate (see below), and sure enough I can
> create a problem. When I create the a bitmap using Scan0 of another
bitmap,
> the data in both bitmaps is modified when either is modified. (As one
would
> expect)
> However, also as you'd expect, by using the .Clone() method on either of
> these bitmaps, you can make this problem go away.
>
> I think my problem may be related to the fact that I'm using an ArrayList
to
> store images as they arrive in my function. I'll troubleshoot this more
> tomorrow...
>
>
>
> private void button1_Click(object sender, System.EventArgs e)
> {
> unsafe
> {
> // create a copy of pictureBox1,
> // using the Scan0 pointer to the bits
> BitmapData bmData = new BitmapData();
> bmData = ((Bitmap)(this.pictureBox1.Image)).LockBits(new Rectangle(new
> Point(0,0),this.pictureBox1.Image.Size),ImageLockMode.ReadWrite,
> this.pictureBox1.Image.PixelFormat);
> Bitmap bm = new Bitmap(bmData.Width, bmData.Height, bmData.Stride,
> bmData.PixelFormat, bmData.Scan0);
> ((Bitmap)(this.pictureBox1.Image)).UnlockBits(bmData);
>
> Graphics g=Graphics.FromImage(bm);
> g.FillEllipse(Brushes.Red,0,0,300,300);
>
> g.Dispose();
>
> this.pictureBox2.Image=bm;
>
> this.pictureBox1.Invalidate();
>
> }
>
> }
>
>
>
> "Bob Powell [MVP]" <bob@_spamkiller_bobpowell.net> wrote in message
> news:Opr2H86FEHA.2576@TK2MSFTNGP11.phx.gbl...
> > hmm, on further investigation I find that I am getting a different copy
of
> > the bits when I do this simple test.
> >
> > private void button1_Click(object sender, System.EventArgs e)
> >
> > {
> >
> > Bitmap bm=(Bitmap)this.pictureBox1.Image.Clone();
> >
> > Graphics g=Graphics.FromImage(bm);
> >
> > g.FillEllipse(Brushes.Red,0,0,300,300);
> >
> > g.Dispose();
> >
> > this.pictureBox2.Image=bm;
> >
> > this.pictureBox1.Invalidate();
> >
> > }
> >
> >
> >
> > Can you post some code to show what you're doing please?
> >
> >
> > --
> > Bob Powell [MVP]
> > Visual C#, System.Drawing
> >
> > All you ever wanted to know about ListView custom drawing is in Well
> Formed.
> > http://www.bobpowell.net/currentissue.htm
> >
> > Answer those GDI+ questions with the GDI+ FAQ
> > http://www.bobpowell.net/gdiplus_faq.htm
> >
> > Read my Blog at http://bobpowelldotnet.blogspot.com
> >
> > "Norvin Laudon" <123@asd.com> wrote in message
> > news:eROSSw6FEHA.3908@TK2MSFTNGP12.phx.gbl...
> > > Thanks Bob.
> > >
> > > Any way I can guarantee a "deep copy" of the bits?
> > >
> > > By the way, I am processing a live video stream. I maintain a 4 image
> FIFO
> > > image queue, which I average together. The average is recalculated as
> each
> > > new frame arrives. Because I need to maintain the integrity of this
> queue,
> > I
> > > need to make sure the same bit data isn't getting "re-used" by the
> > > framework.
> > >
> > > Thanks,
> > > Norvin
> > >
> > > "Bob Powell [MVP]" <bob@_spamkiller_bobpowell.net> wrote in message
> > > news:OMARuO3FEHA.684@tk2msftngp13.phx.gbl...
> > > > Clone of an inmage is not a "deep copy". This is to say that a
> seperate
> > > copy
> > > > of all the bits are not made.
> > > >
> > > > The Clone function calls GdipCloneImage which is not well documented
> but
> > > > which I suspect returns a new handle to the existing image bits.
> > > >
> > > >
> > > > --
> > > > Bob Powell [MVP]
> > > > Visual C#, System.Drawing
> > > >
> > > > All you ever wanted to know about ListView custom drawing is in Well
> > > Formed.
> > > > http://www.bobpowell.net/currentissue.htm
> > > >
> > > > Answer those GDI+ questions with the GDI+ FAQ
> > > > http://www.bobpowell.net/gdiplus_faq.htm
> > > >
> > > > Read my Blog at http://bobpowelldotnet.blogspot.com
> > > >
> > > > "Norvin Laudon" <nospamnorvinll@molinospamenergy.com> wrote in
message
> > > > news:uuQBwn1FEHA.740@tk2msftngp13.phx.gbl...
> > > > > Hi,
> > > > >
> > > > > I am using LockBits to perform some pixel processing on some
Bitmap
> > > > objects.
> > > > >
> > > > > A Bitmap arrives as an argument to an event, where the processing
> > takes
> > > > > place. The processing must be done on a _copy_ of that image, not
on
> > the
> > > > > image itself, so I create a new Bitmap using the .Clone() method
on
> > the
> > > > > original.
> > > > > <code>
> > > > > Bitmap newPic = (Bitmap)originalPic.Clone();
> > > > > </code>
> > > > >
> > > > > With this new bitmap, I use use lockbits and perform the
processing.
> > But
> > > > the
> > > > > original still gets modified! Why is this?
> > > > >
> > > > > I've even tried using the new operator...
> > > > > <code>
> > > > > Bitmap newPic = new Bitmap( (Bitmap)originalPic.Clone() );
> > > > > </code>
> > > > >
> > > > > but the original still gets modified!
> > > > >
> > > > > Any ideas?
> > > > >
> > > > > Thanks,
> > > > > Norvin
> > > > >
> > > > >
> > > >
> > > >
> > >
> > >
> >
> >
>
>
- Next message: Tim Blanton: ".NET PictureBox vs VB6 PictureBox"
- Previous message: Bob Powell [MVP]: "Re: GraphicsPath help please"
- In reply to: Norvin Laudon: "Re: image Clone problem when using LockBits"
- Messages sorted by: [ date ] [ thread ]