Image Crop Issue [modified]
-
Hi all, I am trying to crop an image based on a transparent panel that I have placed on the image. The transparent panel is placed on the image control based on certain coordinates (selected by a user based on mouse events). This works fine. Now I want to try and crop the piece where the transparent panel is located on the image, but I keep receiving an exception:
OutOfMemoryException => rect is outside of the source bitmap bounds.
But why is this happening? (note: The image Bounds value of X and Y is 0 and the transparent panel width and height is in bounds with the height and width of the image) The transparent panel is located within the picturebox, shouldn't it be able to get the correct position :confused: ?? Here is the code ...... TransparentPanel tmpPnl = e.ClickedItem.Tag as TransparentPanel; Rectangle rec = tmpPnl.Bounds; Bitmap bmpImage = new Bitmap(base.Image); Bitmap bmpCrop = bmpImage.Clone(rec, bmpImage.PixelFormat); // exception occurs here ...
FYIThat “out of memory” exception appears when you attempt to crop a piece of the image outside itself.
Eg: If the image is 800×600 and you go:
Bitmap b = CropBitmap(myPic, 700, 500, 200, 200);
That’ll try select from 700×500 to 900×700, which does not actually exist.
Many thanks in advance Kind regards,
The only programmers that are better C# programmers, are those who look like this -> :bob:
:java: Programm3r My Blog: ^_^
modified on Wednesday, September 9, 2009 6:01 AM
-
Hi all, I am trying to crop an image based on a transparent panel that I have placed on the image. The transparent panel is placed on the image control based on certain coordinates (selected by a user based on mouse events). This works fine. Now I want to try and crop the piece where the transparent panel is located on the image, but I keep receiving an exception:
OutOfMemoryException => rect is outside of the source bitmap bounds.
But why is this happening? (note: The image Bounds value of X and Y is 0 and the transparent panel width and height is in bounds with the height and width of the image) The transparent panel is located within the picturebox, shouldn't it be able to get the correct position :confused: ?? Here is the code ...... TransparentPanel tmpPnl = e.ClickedItem.Tag as TransparentPanel; Rectangle rec = tmpPnl.Bounds; Bitmap bmpImage = new Bitmap(base.Image); Bitmap bmpCrop = bmpImage.Clone(rec, bmpImage.PixelFormat); // exception occurs here ...
FYIThat “out of memory” exception appears when you attempt to crop a piece of the image outside itself.
Eg: If the image is 800×600 and you go:
Bitmap b = CropBitmap(myPic, 700, 500, 200, 200);
That’ll try select from 700×500 to 900×700, which does not actually exist.
Many thanks in advance Kind regards,
The only programmers that are better C# programmers, are those who look like this -> :bob:
:java: Programm3r My Blog: ^_^
modified on Wednesday, September 9, 2009 6:01 AM
Ok, so the new method doesn't cause an exception. But the new cropped image's position is a bit out. It crops more to the right. What am I doing wrong?
public static Bitmap CropBitmap(Bitmap srcBitmap, int cropX, int cropY, int cropWidth, int cropHeight) { // Create the new bitmap and associated graphics object Bitmap bmp = new Bitmap(cropWidth, cropHeight); Graphics g = Graphics.FromImage(bmp); // Draw the specified section of the source bitmap to the new one g.DrawImage(srcBitmap, new Rectangle(0, 0, cropWidth, cropHeight), cropX, cropY, cropWidth, cropHeight, GraphicsUnit.Pixel); // Clean up g.Dispose(); // Return the bitmap return bmp; }
Thanks again. Kind regards,The only programmers that are better C# programmers, are those who look like this -> :bob:
:java: Programm3r My Blog: ^_^
-
Hi all, I am trying to crop an image based on a transparent panel that I have placed on the image. The transparent panel is placed on the image control based on certain coordinates (selected by a user based on mouse events). This works fine. Now I want to try and crop the piece where the transparent panel is located on the image, but I keep receiving an exception:
OutOfMemoryException => rect is outside of the source bitmap bounds.
But why is this happening? (note: The image Bounds value of X and Y is 0 and the transparent panel width and height is in bounds with the height and width of the image) The transparent panel is located within the picturebox, shouldn't it be able to get the correct position :confused: ?? Here is the code ...... TransparentPanel tmpPnl = e.ClickedItem.Tag as TransparentPanel; Rectangle rec = tmpPnl.Bounds; Bitmap bmpImage = new Bitmap(base.Image); Bitmap bmpCrop = bmpImage.Clone(rec, bmpImage.PixelFormat); // exception occurs here ...
FYIThat “out of memory” exception appears when you attempt to crop a piece of the image outside itself.
Eg: If the image is 800×600 and you go:
Bitmap b = CropBitmap(myPic, 700, 500, 200, 200);
That’ll try select from 700×500 to 900×700, which does not actually exist.
Many thanks in advance Kind regards,
The only programmers that are better C# programmers, are those who look like this -> :bob:
:java: Programm3r My Blog: ^_^
modified on Wednesday, September 9, 2009 6:01 AM
Hi, can you get the Clone to work if you hard-code the rectangle to say {0, 0, 50, 50}? Try putting a trace on tmpPnl.Bounds too, so you can see what's being passed to Clone - unless tmpPnl is a member of the pictureBox.Controls collection, it's bounds are likely to be relative to the pictureBox.Parent control. Also, wrap up bmpImage var in a using() block to ensure you don't leak memory. Perhaps you could post the code that creates tmpPnl if this doesn't help
"An eye for an eye only ends up making the whole world blind"
-
Hi, can you get the Clone to work if you hard-code the rectangle to say {0, 0, 50, 50}? Try putting a trace on tmpPnl.Bounds too, so you can see what's being passed to Clone - unless tmpPnl is a member of the pictureBox.Controls collection, it's bounds are likely to be relative to the pictureBox.Parent control. Also, wrap up bmpImage var in a using() block to ensure you don't leak memory. Perhaps you could post the code that creates tmpPnl if this doesn't help
"An eye for an eye only ends up making the whole world blind"
Hi, Thanks for the reply.
Rob Smiley wrote:
can you get the Clone to work if you hard-code the rectangle to say {0, 0, 50, 50}?
Yes, it takes the top left-hand corner and computes the correct image result based on the width and the height.
Rob Smiley wrote:
unless tmpPnl is a member of the pictureBox.Controls collection, it's bounds are likely to be relative to the pictureBox.Parent control
The transparent panel is part of the control collection of the image, so it should be in bounds. I think:confused: Values of rec1 and rec2 are the same..
TransparentPanel tmpPnl = e.ClickedItem.Tag as TransparentPanel; Rectangle rec1 = base.Controls[tmpPnl.Name].Bounds; Rectangle rec2 = tmpPnl.Bounds;
The only programmers that are better C# programmers, are those who look like this -> :bob:
:java: Programm3r My Blog: ^_^
-
Hi, Thanks for the reply.
Rob Smiley wrote:
can you get the Clone to work if you hard-code the rectangle to say {0, 0, 50, 50}?
Yes, it takes the top left-hand corner and computes the correct image result based on the width and the height.
Rob Smiley wrote:
unless tmpPnl is a member of the pictureBox.Controls collection, it's bounds are likely to be relative to the pictureBox.Parent control
The transparent panel is part of the control collection of the image, so it should be in bounds. I think:confused: Values of rec1 and rec2 are the same..
TransparentPanel tmpPnl = e.ClickedItem.Tag as TransparentPanel; Rectangle rec1 = base.Controls[tmpPnl.Name].Bounds; Rectangle rec2 = tmpPnl.Bounds;
The only programmers that are better C# programmers, are those who look like this -> :bob:
:java: Programm3r My Blog: ^_^
ok, it sounds like the panel bounds are relative to the pictureBox... hmm. does the image take up the full space in the pictureBox? also have you set a sizeMode on it? e.g. an image smaller than the control area & a size mode of centre or stretch could allow you to have the rectangle appear over the image on screen, but give bounds that are outside the image area. Set sizeMode to normal (so image appears in top-left corner) & see what happens
"An eye for an eye only ends up making the whole world blind"
-
ok, it sounds like the panel bounds are relative to the pictureBox... hmm. does the image take up the full space in the pictureBox? also have you set a sizeMode on it? e.g. an image smaller than the control area & a size mode of centre or stretch could allow you to have the rectangle appear over the image on screen, but give bounds that are outside the image area. Set sizeMode to normal (so image appears in top-left corner) & see what happens
"An eye for an eye only ends up making the whole world blind"
Thanks again for the reply.
Rob Smiley wrote:
does the image take up the full space in the pictureBox?
Yes, I made the image to that it stretches the image.
Rob Smiley wrote:
Set sizeMode to normal (so image appears in top-left corner) & see what happens
- OK, when I change the size mode on the image to normal; all seems to be working. It crops the correct piece relevant to the transparent panel.
- When I change the size mode stretch Image, that's when the issue occurs with the cropped image.
How can I accommodate for the stretched image, I must make use of the stretched size mode, otherwise it will cause problems with an image bigger that the pictureBox control?
The only programmers that are better C# programmers, are those who look like this -> :bob:
:java: Programm3r My Blog: ^_^
-
Thanks again for the reply.
Rob Smiley wrote:
does the image take up the full space in the pictureBox?
Yes, I made the image to that it stretches the image.
Rob Smiley wrote:
Set sizeMode to normal (so image appears in top-left corner) & see what happens
- OK, when I change the size mode on the image to normal; all seems to be working. It crops the correct piece relevant to the transparent panel.
- When I change the size mode stretch Image, that's when the issue occurs with the cropped image.
How can I accommodate for the stretched image, I must make use of the stretched size mode, otherwise it will cause problems with an image bigger that the pictureBox control?
The only programmers that are better C# programmers, are those who look like this -> :bob:
:java: Programm3r My Blog: ^_^
to discover which part of the image you want, you have to apply to your cropping (i.e.mouse) coordinates the same transformation that are being applied to the entire image; so you have to mimick the stretching if you PictureBox is set to stretch mode. That is one of the many problems a PictureBox causes. I almost never use that class, I rather use a simple Panel, and create a Paint handler for it; that way I choose the transformations I want (if any) and I can apply the same transformations to mouse operations. Also, I can then keep the aspect ratio, something a PictureBox isn't really capable of. Conclusion: - apply transformations to all coordinates you get (from mouse handlers) - if possible, get rid of PictureBox :)
Luc Pattyn
Have a look at my entry for the lean-and-mean competition; please provide comments, feedback, discussion, and don’t forget to vote for it! Thank you.
-
to discover which part of the image you want, you have to apply to your cropping (i.e.mouse) coordinates the same transformation that are being applied to the entire image; so you have to mimick the stretching if you PictureBox is set to stretch mode. That is one of the many problems a PictureBox causes. I almost never use that class, I rather use a simple Panel, and create a Paint handler for it; that way I choose the transformations I want (if any) and I can apply the same transformations to mouse operations. Also, I can then keep the aspect ratio, something a PictureBox isn't really capable of. Conclusion: - apply transformations to all coordinates you get (from mouse handlers) - if possible, get rid of PictureBox :)
Luc Pattyn
Have a look at my entry for the lean-and-mean competition; please provide comments, feedback, discussion, and don’t forget to vote for it! Thank you.
Thanks for the reply.
Luc Pattyn wrote:
I rather use a simple Panel, and create a Paint handler for it
:^) Hmmm ... I'll give it a shot Kind regards,
The only programmers that are better C# programmers, are those who look like this -> :bob:
:java: Programm3r My Blog: ^_^
-
Thanks again for the reply.
Rob Smiley wrote:
does the image take up the full space in the pictureBox?
Yes, I made the image to that it stretches the image.
Rob Smiley wrote:
Set sizeMode to normal (so image appears in top-left corner) & see what happens
- OK, when I change the size mode on the image to normal; all seems to be working. It crops the correct piece relevant to the transparent panel.
- When I change the size mode stretch Image, that's when the issue occurs with the cropped image.
How can I accommodate for the stretched image, I must make use of the stretched size mode, otherwise it will cause problems with an image bigger that the pictureBox control?
The only programmers that are better C# programmers, are those who look like this -> :bob:
:java: Programm3r My Blog: ^_^
Hi, you need to do as Luc suggests & scale the rectangle of your cropping area. This should do the trick:
float scaleX = (float)bmpImage.Width / (float)this.ClientSize.Width;
float scaleY = (float)bmpImage.Height / (float)this.ClientSize.Height;rec = new Rectangle((int)(rec.X * scaleX), (int)(rec.Y * scaleY), (int)(rec.Width * scaleX), (int)(rec.Height * scaleY));
"An eye for an eye only ends up making the whole world blind"
-
Hi, you need to do as Luc suggests & scale the rectangle of your cropping area. This should do the trick:
float scaleX = (float)bmpImage.Width / (float)this.ClientSize.Width;
float scaleY = (float)bmpImage.Height / (float)this.ClientSize.Height;rec = new Rectangle((int)(rec.X * scaleX), (int)(rec.Y * scaleY), (int)(rec.Width * scaleX), (int)(rec.Height * scaleY));
"An eye for an eye only ends up making the whole world blind"
Genius!!! Code works like a charm!! :cool::cool: Thanks.
The only programmers that are better C# programmers, are those who look like this -> :bob:
:java: Programm3r My Blog: ^_^
-
Ok, so the new method doesn't cause an exception. But the new cropped image's position is a bit out. It crops more to the right. What am I doing wrong?
public static Bitmap CropBitmap(Bitmap srcBitmap, int cropX, int cropY, int cropWidth, int cropHeight) { // Create the new bitmap and associated graphics object Bitmap bmp = new Bitmap(cropWidth, cropHeight); Graphics g = Graphics.FromImage(bmp); // Draw the specified section of the source bitmap to the new one g.DrawImage(srcBitmap, new Rectangle(0, 0, cropWidth, cropHeight), cropX, cropY, cropWidth, cropHeight, GraphicsUnit.Pixel); // Clean up g.Dispose(); // Return the bitmap return bmp; }
Thanks again. Kind regards,The only programmers that are better C# programmers, are those who look like this -> :bob:
:java: Programm3r My Blog: ^_^