select, cut and replace a region of image with another [closed] - c#

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I have a picture box and import image to this picture box. I want select a region of this picture box (image) like "free-form selection in MS Paint" then cut selected region and replace (fill) this region with another image or a system color.
What is your idea for this problem?!
Thanks.

I wrote a little winform application. There are a lots of things to improve here, but it can give you some advice on how to start.
I used three pictureboxes, one where I displayed the image without changes, a transparent picturebox to select the part of image that I'd like to cut and another one where I can paste the part of the image.
MAIN CODE:
Select:
//I used a rectangle to "select" the part of image
Rectangle imageRegion = new Rectangle(clickedPointOne, pbImageRegion.Size); //clickedPointOne is the point of image where I start to select and pbImageRegion.Size is the size of the part of image.
//Then I cloned the part of image that I want
Image newImage = image.Clone(imageRegion, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Cut:
//I created a new bitmap with the size of the part of image that I selected
Bitmap bmp = new Bitmap(newImage.Width, newImage.Height);
Graphics g = Graphics.FromImage(bmp);
//So here I drawed in the bitmap a rectangle with the picturebox backcolor that rappresent the "blank" part of image
g.FillRectangle(new SolidBrush(mainPictureBox.BackColor), new Rectangle(new Point(0, 0), newImage.Size));
//Now draw the "blank" part on the main image
g = Graphics.FromImage(image);
g.DrawImage(bmp, clickedPointOne);
Replace: (In my application you can paste the part of image wherever in the secondPictureBox)
//Get graphics from the picturebox image (where there could be another image)
Graphics g = Graphics.FromImage(secondPictureBox.Image);
//Draw the part of image
g.DrawImage(newImage, clickedPointTwo); //newImage is the part of image selected and cut, clickedPointTwo is the point of upper-left corner where you want to begin draw the image
THE WHOLE CODE:
private Bitmap image;
private Bitmap newImage;
private Rectangle imageRegion;
private PictureBox pbImageRegion;
private Point clickedPointOne;
private Point clickedPointTwo;
private bool allowMouseMove;
private bool clickedCutButton;
private bool firstClick;
public Form1()
{
InitializeComponent();
mainPictureBox.BackColor = Color.White;
secondPictureBox.BackColor = Color.White;
}
private void loadImageButton_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
image = new Bitmap(ofd.FileName);
mainPictureBox.Image = image;
Bitmap bmp = new Bitmap(image.Width, image.Height);
Graphics g = Graphics.FromImage(bmp);
g.FillRectangle(new SolidBrush(Color.White), new Rectangle(new Point(0, 0), secondPictureBox.Size));
secondPictureBox.Image = bmp;
}
}
private void cutImageButton_Click(object sender, EventArgs e)
{
firstClick = false;
clickedCutButton = true;
allowMouseMove = false;
pbImageRegion = new PictureBox();
pbImageRegion.BackColor = Color.Transparent;
pbImageRegion.BorderStyle = BorderStyle.FixedSingle;
pbImageRegion.Size = new Size(0, 0);
pbImageRegion.MouseMove += new MouseEventHandler(pbImageRegion_MouseMove);
}
void pbImageRegion_MouseMove(object sender, MouseEventArgs e)
{
if (allowMouseMove == true)
pbImageRegion.Size = new Size(Math.Abs(e.X - clickedPointOne.X - 2), Math.Abs(e.Y - clickedPointOne.Y - 2));
}
private void mainPictureBox_MouseClick(object sender, MouseEventArgs e)
{
if (clickedCutButton == true)
{
if (e.Button == MouseButtons.Left)
{
if (firstClick == false)
{
pbImageRegion.Location = new Point(e.X, e.Y);
mainPictureBox.Controls.Add(pbImageRegion);
clickedPointOne = new Point(e.X, e.Y);
allowMouseMove = true;
firstClick = true;
}
else
{
imageRegion = new Rectangle(clickedPointOne, pbImageRegion.Size);
newImage = image.Clone(imageRegion, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
allowMouseMove = false;
mainPictureBox.Invalidate();
}
}
}
}
private void mainPictureBox_MouseMove(object sender, MouseEventArgs e)
{
//It works only from left to right
if (allowMouseMove == true)
pbImageRegion.Size = new Size(Math.Abs(e.X - clickedPointOne.X - 2), Math.Abs(e.Y - clickedPointOne.Y - 2));
}
private void secondPictureBox_MouseClick(object sender, MouseEventArgs e)
{
if (clickedCutButton == true)
{
if (e.Button == MouseButtons.Left)
{
clickedCutButton = false;
pbImageRegion.Size = new Size(0, 0);
clickedPointTwo = new Point(e.X, e.Y);
secondPictureBox.Invalidate();
}
}
}
private void secondPictureBox_Paint(object sender, PaintEventArgs e)
{
if (newImage != null)
{
Graphics g = Graphics.FromImage(secondPictureBox.Image);
g.DrawImage(newImage, clickedPointTwo);
e.Graphics.DrawImage(secondPictureBox.Image, new Point(0, 0));
}
}
private void mainPictureBox_Paint(object sender, PaintEventArgs e)
{
if (newImage != null && allowMouseMove == false)
{
Bitmap bmp = new Bitmap(newImage.Width, newImage.Height);
Graphics g = Graphics.FromImage(bmp);
g.FillRectangle(new SolidBrush(mainPictureBox.BackColor), new Rectangle(new Point(0, 0), newImage.Size));
g = Graphics.FromImage(image);
g.DrawImage(bmp, clickedPointOne);
}
}

Related

Save Drawn Images PictureBox [duplicate]

This question already has answers here:
How to save graphics created on a PictureBox?
(2 answers)
Closed 2 years ago.
My program allows the user to draw in a PictureBox.
I'm trying to save the pictureBox1 as a .jpg file but this file is empty.
My save button:
Bitmap bm = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
this.pictureBox1.DrawToBitmap(bm, this.pictureBox1.ClientRectangle);
bm.Save(String.Format("{0}.jpg", this.ID));
this.pictureBox1.CreateGraphics().Clear(Color.White);
My draw event:
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
drawNote.isDraw = true;
drawNote.X = e.X;
drawNote.Y = e.Y;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if(drawNote.isDraw)
{
Graphics G = pictureBox1.CreateGraphics();
G.DrawLine(drawNote.pen, drawNote.X, drawNote.Y, e.X, e.Y);
drawNote.X = e.X;
drawNote.Y = e.Y;
}
}
You should create an empty Bimap set pictureBox1.Image by this bitmap then creat graphics from it, also you must store it in global variable to prevent recreat it.
Like this:
Graphics graphics = null;
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if(drawNote.isDraw)
{
if (graphics == null)
{
graphics = pictureBox1.CreateGraphics();
Bitmap bmp = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
pictureBox1.Image = bmp;
graphics = Graphics.FromImage(bmp);
graphics.Clear(Color.White);
}
graphics.DrawLine(drawNote.pen, drawNote.X, drawNote.Y, e.X, e.Y);
graphics.Flush();
graphics.Save();
pictureBox1.Refresh();
drawNote.X = e.X;
drawNote.Y = e.Y;
}
}
And you could do this by this simple code:
using (FileStream fileStream = new FileStream(#"C:\test.jpg", FileMode.Create))
{
pictureBox1.Image.Save(fileStream, System.Drawing.Imaging.ImageFormat.Jpeg);
}

I can not find the error in the code.a picture Box does not update

I'm creating a software in which pictureBox2 updates with the color of the pixel clicked on pictureBox1.
Already tried to use refresh(), but pictureBox2 does not change.
private void PictureBox1_MouseUp(object sender, MouseEventArgs e)
{
Bitmap b = new Bitmap(pictureBox1.Image);
color = b.GetPixel(e.X, e.Y); // Color
solidColor = new Bitmap(pictureBox2.Width, pictureBox2.Height, PixelFormat.Format24bppRgb); //Image
using (Graphics grp = Graphics.FromImage(solidColor))
{
SolidBrush co = new SolidBrush(color);
grp.FillRectangle( co, 0, 0, pictureBox2.Width, pictureBox2.Height);
}
pictureBox2.Image = solidColor;
}
I was able to solve this by doing this.
private void PictureBox1_Click(object sender, EventArgs e)
{
Bitmap b = new Bitmap(pictureBox1.Image);
MouseEventArgs me = (MouseEventArgs)e;
Point cord= me.Location;
color = b.GetPixel(cord.X,cord.Y);
solidColor = new Bitmap(pictureBox2.Width, pictureBox2.Height, PixelFormat.Format24bppRgb);
using (Graphics grp = Graphics.FromImage(solidColor))
{
SolidBrush co = new SolidBrush(color);
grp.FillRectangle(co, 0, 0, pictureBox2.Width, pictureBox2.Height);
}
pictureBox2.Image = solidColor;
}
```c#

C# ImageBox Clear Rectangle on MouseUp

I have a panel with multiple picturebox created at runtime.
The user will create a rectangle on any picture box and the selected part will be displayed on a preview picturebox.
I have successfully done the above using the below code.
Question
I want to clear the selection rectangle at mouseup event. Used invalidate but not working.
From how to clear the graphics(rectangle shape) in picturebox
Also, when I scroll the panel the same rectangle(mouse selection) is shown on all picturebox.
private void Picture_Paint(object sender, PaintEventArgs e)
{
if (Rect!=null && Rect.Width>0 && Rect.Height>0)
{
e.Graphics.FillRectangle(selectionBrush, Rect);
}
}
private void Picture_MouseDown(object sender, MouseEventArgs e)
{
RecStartpoint = e.Location;
((PictureBox)sender).Invalidate();
}
private void Picture_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
Point tempEndPoint = e.Location;
Rect.Location = new Point(
Math.Min(RecStartpoint.X, tempEndPoint.X),
Math.Min(RecStartpoint.Y, tempEndPoint.Y));
Rect.Size = new Size(
Math.Abs(RecStartpoint.X - tempEndPoint.X),
Math.Abs(RecStartpoint.Y - tempEndPoint.Y));
((PictureBox)sender).Invalidate();
}
private void Picture_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
PictureBox org_pic = (PictureBox)(sender);
Point RecEndpoint=e.Location;
int xDown = Math.Min(RecStartpoint.X,RecEndpoint.X);
int yDown = Math.Min(RecStartpoint.Y, RecEndpoint.Y);
int xUp = Math.Max(RecStartpoint.X,RecEndpoint.X);
int yUp = Math.Max(RecStartpoint.Y,RecEndpoint.Y);
Rectangle rec = new Rectangle(xDown, yDown, Math.Abs(xUp - xDown), Math.Abs(yUp - yDown));
xDown = xDown * org_pic.Image.Width / org_pic.Width;
yDown = yDown * org_pic.Image.Height / org_pic.Height;
xUp = xUp * org_pic.Image.Width / org_pic.Width;
yUp = yUp * org_pic.Image.Height / org_pic.Height;
rectCropArea = new Rectangle(xDown, yDown, Math.Abs(xUp - xDown), Math.Abs(yUp - yDown));
pictureBox_preview_photo.Refresh();
Bitmap sourceBitmap = new Bitmap(org_pic.ImageLocation);
Graphics g = pictureBox_preview_photo.CreateGraphics();
g.DrawImage(sourceBitmap, new Rectangle(0, 0, pictureBox_preview_photo.Width, pictureBox_preview_photo.Height), rectCropArea, GraphicsUnit.Pixel);
}
I would try this approach:
First, make Image variable, in the scope of form
public partial class Form1 : Form
{
//variable for holding original image, before rectangle is drawn on it
Image originalImage = null;
public Form1()
{
InitializeComponent();
}
//rest of form's code...
second, save current picture in that variable on MouseDown
private void Picture_MouseDown(object sender, MouseEventArgs e)
{
//save it
startImage = ((PictureBox)sender).Image;
RecStartpoint = e.Location;
((PictureBox)sender).Invalidate();
}
lastly, on the end of MouseUp event, set Rectangle's width and height to zero and restore saved, original image
//snipped code
pictureBox_preview_photo.Refresh();
Bitmap sourceBitmap = new Bitmap(org_pic.ImageLocation);
Graphics g = pictureBox_preview_photo.CreateGraphics();
g.DrawImage(sourceBitmap, new Rectangle(0, 0, pictureBox_preview_photo.Width, pictureBox_preview_photo.Height), rectCropArea, GraphicsUnit.Pixel);
//make rectangle's widht and height 0 so that Paint event won't draw it
Rect.Width = Rect.Height = 0;
//restore image
this.Picture.Image = startImage;
I didn't understand that second question.

How to get a DataGridView Row as Bitmap for a cursor icon?

I'm trying to get a DataGridViews row as Bitmap to use it as a cursors icon.
Sadly the DataGridViewRow object has no DrawToBitmap method.
I managed to get the bound of the row (RowRect) and get a Bitmap of the whole DataGridView (bmp). I think I next need to cut the row from the bitmap, but I have no idea how to do that.
Here is my starting code:
private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
if (dataGridView1.SelectedRows.Count == 1)
{
if (e.Button == MouseButtons.Left)
{
rw = dataGridView1.SelectedRows[0];
Rectangle RowRect = dataGridView1.GetRowDisplayRectangle(rw.Index, true);
Bitmap bmp = new Bitmap(RowRect.Width, RowRect.Height);
dataGridView1.DrawToBitmap(bmp, new Rectangle(Point.Empty, bmp.Size));
Cursor cur = new Cursor(bmp.GetHicon());
Cursor.Current = cur;
rowIndexFromMouseDown = dataGridView1.SelectedRows[0].Index;
dataGridView1.DoDragDrop(rw, DragDropEffects.Move);
}
}
}
You need to grab the whole clientarea content first (your bitmap is too small!), then cut out the row rectangle. Also make sure to dispose of the created resources!
This should work:
private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
if (dataGridView1.SelectedRows.Count == 1)
{
if (e.Button == MouseButtons.Left)
{
Size dgvSz = dataGridView1.ClientSize;
int rw = dataGridView1.SelectedRows[0].Index;
Rectangle RowRect = dataGridView1.GetRowDisplayRectangle(rw, true);
using (Bitmap bmpDgv = new Bitmap(dgvSz.Width, dgvSz.Height))
using (Bitmap bmpRow = new Bitmap(RowRect.Width, RowRect.Height))
{
dataGridView1.DrawToBitmap(bmpDgv , new Rectangle(Point.Empty, dgvSz));
using ( Graphics G = Graphics.FromImage(bmpRow ))
G.DrawImage(bmpDgv , new Rectangle(Point.Empty,
RowRect.Size), RowRect, GraphicsUnit.Pixel);
Cursor.Current.Dispose(); // not quite sure if this is needed
Cursor cur = new Cursor(bmpRow .GetHicon());
Cursor.Current = cur;
rowIndexFromMouseDown = dataGridView1.SelectedRows[0].Index;
dataGridView1.DoDragDrop(rw, DragDropEffects.Move);
}
}
}
}

Crop and load tiled image in picturebox c#

I have a tiled image like https://i.imgsafe.org/67397f9.png and want to load its parts as image for a picture box in some mouse events. actually I want simulate button behavior.
Bitmap source = new Bitmap(Properties.Resources.btn_close);
public Bitmap CropImage(Bitmap srcbmp, Rectangle dstcrp)
{
Bitmap bmp = new Bitmap(dstcrp.Width, dstcrp.Height);
Graphics gfx = Graphics.FromImage(bmp);
gfx.DrawImage(srcbmp, 0, 0, dstcrp, GraphicsUnit.Pixel);
return bmp;
}
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
Rectangle section = new Rectangle(new Point(0, 93), new Size(51, 30));
pictureBox1.Image = CropImage(source, section);
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
Rectangle section = new Rectangle(new Point(0, 93), new Size(51, 30));
pictureBox1.Image = CropImage(source, section);
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
Rectangle section = new Rectangle(new Point(0, 62), new Size(51, 30));
pictureBox1.Image = CropImage(source, section);
}
private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
Rectangle section = new Rectangle(new Point(0, 0), new Size(51, 30));
pictureBox1.Image = CropImage(source, section);
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
Rectangle section = new Rectangle(new Point(0, 0), new Size(51, 30));
pictureBox1.Image = CropImage(source, section);
}
this is my codes that crop sections of image and load as bitmap for picture box.
I think it is not very professional and may have some memory usage problems, etc...
is there any simple way to do this?
2 solutions which i can think of
When you first load the form you can declare 4 image/bitmap variables 1 for each Mouse State Mouse Down, Leave Up and Enter so instead of recrating the images again and again you can just change the image when time is right.
var cropCoordinates= new Rectangle(new Point(0, 0), new Size(51, 30));
var onMouseDownImage = new Bitmap(Properties.Resources.btn_close);
You can have 4 different image boxes for each state (layered 1 on top of the other )and show or hide when the time is needed

Categories