Image cropping issue in C# - c#

In my asp.net C# application, I am trying to crop the below image:
I have selected only the face part, but the cropped image always selecting from top left corner like below:
I am using the below code to crop image:
Rectangle sourceRect = new Rectangle(iX1, iY1, w, h);
System.Drawing.Image imgNew = CropImage(imgOrig, sourceRect);
private static System.Drawing.Image CropImage(System.Drawing.Image img, Rectangle cropArea)
{
Bitmap bmpImage = new Bitmap(img);
Bitmap bmpCrop = bmpImage.Clone(cropArea, bmpImage.PixelFormat);
img.Dispose();
return (System.Drawing.Image)bmpCrop;
}

Use this code to crop your image.
static Bitmap CropImage(Image originalImage, Rectangle sourceRectangle, Rectangle destinationRectangle)
{
var croppedImage = new Bitmap(destinationRectangle.Width, destinationRectangle.Height);
using (var graphics = Graphics.FromImage(croppedImage))
{
graphics.DrawImage(originalImage, destinationRectangle, sourceRectangle, GraphicsUnit.Pixel);
}
return croppedImage;
}
The problem is that your original algorithm doesn't specify where to start cropping from. It therefore always starts from the origin, which is not what you want.

Related

Screenshot conversion into grayscale doesn't work. What causes this?

I have a Windows Forms application that takes a screenshot of a specific portion of the screen, then displays it in a picture box (pictureBox1). It works when I don't try to convert it, but I want to convert the image to grayscale or black and white. The problem is when I convert it to grayscale, it still shows the original picture in the picture box.
Here is the code when it works, without the conversion:
private void button1_Click(object sender, EventArgs e)
{
Rectangle rectangle = new Rectangle(660, 200, 600, 100);
pictureBox1.Height = rectangle.Height;
pictureBox1.Width = rectangle.Width;
imageUploader(rectangle);
}
public void imageUploader(Rectangle rectangle)
{
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
bitmap.Save("proba.jpeg", ImageFormat.Jpeg);
pictureBox1.Image = bitmap;
}
Here is the conversion method, which I tried out:
public void toGrayscale(Bitmap bitmap)
{
Color c;
for (int y = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
c = bitmap.GetPixel(x,y);
Color newColor = Color.FromArgb(c.R,0,0);
bitmap.SetPixel(x,y,newColor);
}
}
}
After I used this conversion (see below) the image showed up in the picture box, but it wasn't grayscale.
Here is the modified imageUploader void with the conversion:
public void imageUploader(Rectangle rectangle)
{
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
toGrayscale(bitmap);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
bitmap.Save("proba.jpeg", ImageFormat.Jpeg);
pictureBox1.Image = bitmap;
}
It appears that your issue is here:
public void imageUploader(Rectangle rectangle)
{
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
toGrayscale(bitmap);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
bitmap.Save("proba.jpeg", ImageFormat.Jpeg);
pictureBox1.Image = bitmap;
}
You're converting each pixel of the bitmap to greyscale (oddly it looks like you're only grabbing the red channel) then copying from the screen, which overwrites your conversion. To fix it, all you should need to do is move the toGreyscale after you copy from the screen, like this:
public void imageUploader(Rectangle rectangle)
{
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
toGrayscale(bitmap); # Moved after the copy from screen
bitmap.Save("proba.jpeg", ImageFormat.Jpeg);
pictureBox1.Image = bitmap;
}
This should fix the issue.
You are converting an empty Bitmap to greyscale, then copying over the (nominally) greyscaled Bitmap with an image from the screen. Here is your code, annotated to describe what it is doing:
// This line creates an empty Bitmap.
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
// This line converts the empty Bitmap to grayscale.
toGrayscale(bitmap);
// This line creates a Graphics drawing surface from your bitmap.
Graphics graphics = Graphics.FromImage(bitmap);
// This line overwrites the image data from your bitmap with an image from the screen.
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
You need to find some way to take the data you got from the screen and make it greyscale. You have not done this. You have made a greyscale image, but then you have thrown it away by writing other data on top of it. It happens that that replacement data is not greyscale.

Get bitmap and draw it into image

I am trying to save my drawing from picturebox into bitmap and draw that bitmap into image. So far, nothing has appeared in the final image, but while debugging I can only say, that the original bitmap is not null and with/height are correct. However nothing appears after I draw it into image.
I save my drawing into bitmap like this:
GraphicsPath path = RoundedRectangle.Create(x, y, width, height, corners, RoundedRectangle.RectangleCorners.All);
g.FillPath(Brushes.LightGray, path);
g.SetClip(path);
using (Font f = new Font("Tahoma", 9, FontStyle.Bold))
g.DrawString(mtb_hotspotData.Text, f, Brushes.Black, textX, textY);
g.ResetClip();
bitmap = new Bitmap(width, height, g);
Then save it:
hs.bitmap = new Bitmap(bitmap);
And finally use it:
for (int i = 0; i < imageSequence.Count; i++) {
Graphics g = Graphics.FromImage(imageSequence[i]);
//g.CompositingMode = CompositingMode.SourceOver;
//hotspot.bitmap.MakeTransparent();
int x = hotspot.coordinates[i].X;
int y = hotspot.coordinates[i].Y;
g.DrawImage(hotspot.bitmap, new Point(x, y));
}
return imageSequence;
So far I was not able to find any problem in this solution, therefore I have no idea, where the malfunction is.
You seem to misunderstand the relation of a Bitmap and a Graphics object.
A Graphics object does not contain any graphics; it is a tool used to draw into a bitmap of some sort.
The Bitmap constructor you are using (public Bitmap(int width, int height, Graphics g)) does not really connect the Bitmap and the Graphics object. It only uses the dpi resolution from the Graphics.
You don't show how your Graphics is created. If you want to draw into a Bitmap (as opposed to a control's surface) the most direct way is this:
Bitmap bitmap = new Bitmap(width, height);
bitmap.SetResolution(dpiX, dpiY); // optional
using (Graphics G = Graphics.FromImage(bitmap ))
{
// do the drawing..
// insert all your drawing code here!
}
// now the Bitmap can be saved or cloned..
bitmap.Save(..);
hs.bitmap = new Bitmap(bitmap); // one way..
hs.bitmap = bitmap.Clone(); // ..or the other
// and finally disposed of (!!)
bitmap.Dispose();

Drawing transparent pixels in pictureBox C#

I have a picture box, and import a .png picture into.
Now when I rotate the actual image, the "free" space of the picture box, that does not include the image is filled by black pixels.
Q: How to make that black pixels transparent?
Edit:
Here is the rotation code
public static Bitmap RotateImage(Image image, PointF offset, float angle)
{
if (image == null)
{
return null;
}
try
{
Bitmap rotatedBmp = new Bitmap(image.Width, image.Height);
rotatedBmp.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (Graphics g = Graphics.FromImage(rotatedBmp))
{
g.TranslateTransform(offset.X, offset.Y);
g.RotateTransform(angle);
g.TranslateTransform(-offset.X, -offset.Y);
g.DrawImage(image, new Point(0, 0));
}
return rotatedBmp;
}
catch (OutOfMemoryException)
{
GC.Collect();
}
catch (ArgumentException)
{
}
return image as Bitmap;
}
Here are original and modified images:
PictureBox supports transparency if you set the SupportsTransparentBackColor property of System.Windows.Forms.ControlStyles to true, put this in your Form_Load.
this.SetStyle(System.Windows.Forms.ControlStyles.SupportsTransparentBackColor, true);
You can set BackColor on the PictureBox to another colour if you wish, by default it will be DefaultBackColor.

Cropping Images .Net

I am trying to do a simple crop of an image, but for some reason it is not respecting my starting x,y location. It is always starting the crop at 0,0. The following is what I am doing:
Bitmap original = new Bitmap(pictureBox1.Image);
int x = Convert.ToInt32(txtX.Text);
int y = Convert.ToInt32(txtY.Text);
int dX = Convert.ToInt32(txtDeltaX.Text);
int dY = Convert.ToInt32(txtDeltaY.Text);
Point loc = new Point(x, y);
Size cropSize = new Size(dX, dY);
Rectangle cropArea = new Rectangle(loc, cropSize);
Bitmap bmpCrop = CropImage(original, cropArea);
pictureBox1.Image = bmpCrop;
The cropping method:
public Bitmap CropImage(Bitmap source, Rectangle section)
{
// An empty bitmap which will hold the cropped image
Bitmap bmp = new Bitmap(section.Width, section.Height);
Graphics g = Graphics.FromImage(bmp);
// Draw the given area (section) of the source image
// at location 0,0 on the empty bitmap (bmp)
g.DrawImage(source, 0, 0, section, GraphicsUnit.Pixel);
return bmp;
}
This should be very simple, but for some reason its not working. Its cropping it, just at 0,0.
Thanks!
You should try to use
g.DrawImage(source, section);
Anyway this function works:
public Bitmap CropBitmap(Bitmap bitmap,
int cropX, int cropY,
int cropWidth, int cropHeight)
{
Rectangle rect = new Rectangle(cropX, cropY, cropWidth, cropHeight);
Bitmap cropped = bitmap.Clone(rect, bitmap.PixelFormat);
return cropped;
}
You might want to use Graphics.DrawImageUnscaledAndClipped
Try to use, something like this :
g.DrawImage(source, x, y, section, GraphicsUnit.Pixel);

C#. Crop image on N rectangles

I need to crop image on N rectangles.
Condition for all rectangles:
Rectangle's width = X
Rectangle's height = X/2
Any algorithm ?
This can help you:
private static Image cropImage(Image img, Rectangle cropArea)
{
Bitmap bmpImage = new Bitmap(img);
Bitmap bmpCrop = bmpImage.Clone(cropArea,
bmpImage.PixelFormat);
return (Image)(bmpCrop);
}
I found a more complex but complete example here:
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/e0c30a26-60da-457d-a217-ba95650deec8

Categories