2016-11-20 56 views
1

我製作了一個程序,可以讓您隨機選擇一個區域,然後將選定區域保存爲一張新圖像,但是我遇到了一個問題,它無法正常工作。 ..我會在這裏發佈我的代碼,所以你可以看看:自由形式的作物選擇無法正常工作

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

+0

您需要可以設置大小模式爲普通而不是縮放,或者也需要縮放選定的點。 – TaW

+1

是的,它的工作原理,但我需要讓我的圖像也延伸到圖片框。 如何縮放選定的點? –

回答

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)); 

您的調整後PictureBox設置Image後計算這個..

現在你可以轉換每個繪製點放大或放大座標:

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)); 
    } 

下面是一個演示程序,左)或放大(中)圖像。右邊是一個checkerbox背景放置您的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 

在此之後由一個替換到unzoomedPoints在該方法中的每個參考到points。其實只有兩個人..

案例2:如果您已存儲「未縮放」的要點:

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

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

+0

TaW,你對這個問題有什麼想法嗎? http://stackoverflow.com/questions/40784541/issue-with-cropping-on-webcam –

+0

那麼你需要做一個Points.Clear加載一個新的圖像時,我會說。我在測試時注意到了它。 – TaW

+0

和關於裁剪而不用相機捕捉的部分? –