[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.dotnet.framework.drawing

Re: image Clone problem when using LockBits

daver

1/3/2005 3:06:00 PM


Norvin Laudon wrote:
> 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/curren...
> > >
> > > Answer those GDI+ questions with the GDI+ FAQ
> > > http://www.bobpowell.net/gdipl...
> > >
> > > Read my Blog at http://bobpowelldotnet.bl...
> > >
> > > "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/curren...
> > > > >
> > > > > Answer those GDI+ questions with the GDI+ FAQ
> > > > > http://www.bobpowell.net/gdipl...
> > > > >
> > > > > Read my Blog at http://bobpowelldotnet.bl...
> > > > >
> > > > > "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
> > > > > >
> > > > > >
> > > > >
> > > > >
> > > >
> > > >
> > >
> > >
> >
> >


I believe the Clone() method instead of using extra space, uses a base
image. This base image would be the first bitmap that was created.
All cloned objects are based on the original as to conserve memory. I
fell for it too, I am looking for a way around it now..

Dave