自由形式的作物选择不能正常工作

时间:2016-11-20 15:29:08

标签: c#

我做了一个程序,让你随机选择然后选择区域保存到一个新的图像,但我遇到了一个问题,它没有工作如何应该......我会在此处发布我的代码,以便您可以查看:

private List<Point> Points = null;
private bool Selecting = false;
private Bitmap SelectedArea = null;

private void pictureBox5_MouseDown(object sender, MouseEventArgs e)
{
  Points = new List<Point>();
  Selecting = true;
}

private void pictureBox5_MouseMove(object sender, MouseEventArgs e)
{
  if (!Selecting) return;
  Points.Add(new Point(e.X, e.Y));
  pictureBox5.Invalidate();
}

private void pictureBox5_MouseUp(object sender, MouseEventArgs e)
{
  Selecting = false;

  // Copy the selected area.
  SelectedArea = GetSelectedArea(pictureBox5.Image, Color.Transparent, Points);

  SelectedArea.Save(@"C:\Users\User\Desktop\Gallery\image" + NumberOfClick.ToString() + "cropped.jpeg", ImageFormat.Jpeg);

  string filename = @"C:\Users\User\Desktop\Gallery\image" + NumberOfClick.ToString() + "cropped.jpeg";

  if(File.Exists(filename))
  {
    button1.Visible = true;
    pictureBox5.Visible = false;
  }
}

private void pictureBox5_Paint(object sender, PaintEventArgs e)
{
  if ((Points != null) && (Points.Count > 1))
  {
    using (Pen dashed_pen = new Pen(Color.Black))
    {
      dashed_pen.DashPattern = new float[] { 5, 5 };
      e.Graphics.DrawLines(Pens.White, Points.ToArray());
      e.Graphics.DrawLines(dashed_pen, Points.ToArray());
    }
  }
}

private Bitmap GetSelectedArea(Image source, Color bg_color, List<Point> points)
{
  // Make a new bitmap that has the background
  // color except in the selected area.
  Bitmap big_bm = new Bitmap(source);
  using (Graphics gr = Graphics.FromImage(big_bm))
  {
    // Set the background color.
    gr.Clear(bg_color);

    // Make a brush out of the original image.
    using (Brush br = new TextureBrush(source))
    {
      // Fill the selected area with the brush.
      gr.FillPolygon(br, points.ToArray());

      // Find the bounds of the selected area.
      Rectangle source_rect = GetPointListBounds(points);

      // Make a bitmap that only holds the selected area.
      Bitmap result = new Bitmap(
        source_rect.Width, source_rect.Height);

      // Copy the selected area to the result bitmap.
      using (Graphics result_gr = Graphics.FromImage(result))
      {
        Rectangle dest_rect = new Rectangle(0, 0,
                                            source_rect.Width, source_rect.Height);
        result_gr.DrawImage(big_bm, dest_rect,
                            source_rect, GraphicsUnit.Pixel);
      }

      // Return the result.
      return result;
    }
  }
}

private Rectangle GetPointListBounds(List<Point> points)
{
  int xmin = points[0].X;
  int xmax = xmin;
  int ymin = points[0].Y;
  int ymax = ymin;

  for (int i = 1; i < points.Count; i++)
  {
    if (xmin > points[i].X) xmin = points[i].X;
    if (xmax < points[i].X) xmax = points[i].X;
    if (ymin > points[i].Y) ymin = points[i].Y;
    if (ymax < points[i].Y) ymax = points[i].Y;
  }

  return new Rectangle(xmin, ymin, xmax - xmin, ymax - ymin);
}

这就是我正在做的事情并保存裁剪的图像。

这也是我上传图片的方式:

OpenFileDialog f = new OpenFileDialog();
f.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) | *.jpg; *.jpeg; *.jpe; *.jfif; *.png";

if (f.ShowDialog() == DialogResult.OK)
{
  currentImage = Image.FromFile(f.FileName);
  pictureBox1.Image = currentImage;
}

pictureBox1.Image.Save(@"C:\Users\User\Desktop\Gallery\image1.jpeg", ImageFormat.Jpeg);

DialogResult result = MessageBox.Show("Crop your image", "Information", MessageBoxButtons.OK);

if(result == DialogResult.OK)
{
  pictureBox5.Visible = true;
  button1.Visible = false;
  pictureBox5.Image = pictureBox1.Image;
}

在pictureBox5中,我正在选择并裁剪图片。

mySelection croppedImage

1 个答案:

答案 0 :(得分:3)

缩放时,您需要计算图像的缩放偏移

以下是如何做到这一点;这假设PictureBox确实处于Zoom模式,而不是Stretch模式。如果你拉伸它,你需要计算x和y的缩放单独 ..

SizeF sp = pictureBox5.ClientSize;
SizeF si = pictureBox5.Image.Size;    
float rp = sp.Width / sp.Height;   // calculate the ratios of
float ri = si.Width / si.Height;   // pbox and image   

float zoom = (rp > ri) ? sp.Height / si.Height : sp.Width / si.Width;

float offx = (rp > ri) ? (sp.Width - si.Width * zoom) / 2 : 0;
float offy = (rp <= ri)? (sp.Height - si.Height * zoom) / 2 : 0;
Point offset = Point.Round(new PointF(offx, offy));

您在调整Image的尺寸后设置PictureBox 后计算出来了。

现在,您可以将每个绘制点转换为缩放坐标或非坐标坐标:

    PointF zoomed(Point p1, float zoom, Point offset)
    {
        return (new PointF(p1.X * zoom + offset.X, p1.Y * zoom + offset.Y));
    }

    PointF unZoomed(Point p1, float zoom, Point offset)
    {
        return (new PointF((p1.X - offset.X) / zoom, (p1.Y - offset.Y) / zoom));
    }

这是一个绘制正常(左)或放大(中)图像的演示。右侧是将GetSelectedArea位图放置在带有检查框背景的PictureBox上的结果:

enter image description here

案例1:如果您将积分存入:在GetSelectedArea方法中,请使用此点列表:

    private Bitmap GetSelectedArea(Image source, Color bg_color, List<Point> points)
    {
        var unzoomedPoints = 
            points.Select(x => Point.Round((unZoomed(Point.Round(x), zoom, offset))))
                  .ToList();
        // Make a new bitmap that has the background

在此之后,将方法中的points的每个引用替换为unzoomedPoints。实际上只有两个..

案例2:如果您存储的点已经“unZoomed”:

Points.Add(unZoomed(e.Location, zoom, offset));

您可以直接使用该列表..