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.
I am developing an application for image processing. To zoom the image, I enlarge PictureBox. But after enlarging I get below image as result.
But I want result like below image
Here is my Code :
picturebox1.Size = new Size((int)(height * zoomfactor), (int)
(width* zoomfactor));
this.picturebox1.Refresh();
The PictureBox by itself will always create a nice and smooth version.
To create the effect you want you need to draw zoomed versions yourself. In doing this you need to set the
Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
Then no blurring will happen..
Example:
private void trackBar1_Scroll(object sender, EventArgs e)
{
Bitmap bmp = (Bitmap)pictureBox1.Image;
Size sz = bmp.Size;
Bitmap zoomed = (Bitmap)pictureBox2.Image;
if (zoomed != null) zoomed.Dispose();
float zoom = (float)(trackBar1.Value / 4f + 1);
zoomed = new Bitmap((int)(sz.Width * zoom), (int)(sz.Height * zoom));
using (Graphics g = Graphics.FromImage(zoomed))
{
if (cbx_interpol.Checked) g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.PixelOffsetMode = PixelOffsetMode.Half;
g.DrawImage(bmp, new Rectangle( Point.Empty, zoomed.Size) );
}
pictureBox2.Image = zoomed;
}
Of course you need to avoid setting the PBox to Sizemode Zoom or Stretch!
I want to show a Resized Picture in my Picturebox.
The original picture is:
And the Picture in my form:
My picturebox size is 500x500px.
My method that I use for the resize:
public static Image ResizePicByWidth(Image sourceImage, double newWidth)
{
double sizeFactor = newWidth / sourceImage.Width;
double newHeigth = sizeFactor * sourceImage.Height;
Bitmap newImage = new Bitmap((int)newWidth, (int)newHeigth);
using (Graphics g = Graphics.FromImage(newImage))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.DrawImage(sourceImage, new Rectangle(0, 0, (int)newWidth, (int)newHeigth));
}
return newImage;
}
I call the method with the original picture and the width from the picturebox.
But how can i resize the picture correctly?
I want my Form to show the whole Picture.
PictureBox has a SizeMode property. If you set this to Zoom it will automatically resize the image in it to fit inside it.
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.
I've seen this tutorial on how to capture the screen with cursor.
Now I added a timer and datagridview and I want to save every capture in the datagridview. Here is what I did:
private void Display(Bitmap desktop)
{
Graphics g;
Rectangle r;
if (desktop != null)
{
r = new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height);
g = pictureBox1.CreateGraphics();
g.DrawImage(desktop, r);
g.Flush();
Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height, g);
dataGridView1.Rows.Add(bmp);
}
}
But all I get is white images like this:
I can't reach the point where I can save what appear on picturebox and add it to the datagridview
Using CreateGraphics is a temporary drawing on the screen, so the image isn't getting transferred to the bitmap.
Try drawing directly instead:
private void Display(Bitmap desktop) {
if (desktop != null) {
Bitmap bmp = new Bitmap(pictureBox1.ClientSize.Width,
pictureBox1.ClientSize.Height);
using (Graphics g = Graphics.FromImage(bmp)) {
g.DrawImage(desktop, Point.Empty);
}
pictureBox1.Image = bmp;
dataGridView1.Rows.Add(bmp);
}
}