C# 图片裁剪
之前用C#做了一个简单的图片裁剪项目,记录一下。
实现功能
- 实现点击按钮,选择一张图片,打开、显示;
- 点击按钮,用鼠标拖动画一个矩形框;
- 点击按钮,将矩形框内的图片裁剪并保存成一副新的图片.
- 支持图片角度调整
运行界面效果
winForm控件
注意还有图中左下角的两个控件
引用和定义:
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection;
using System.Windows.Forms;
using System.IO;
using System.Drawing.Drawing2D;
namespace xxxx
{
public partial class Form1 : Form
{
bool blnDraw;
Point start; //画框的起始点
Rectangle rect;
Point Pstart; //原图的起始点
Rectangle Orect;//在原图中尺寸
private string filePath = string.Empty;
public Form1()
{
InitializeComponent();
}
.....
}
}
Windows 窗体的 OpenFileDialog(打开文件对话框)组件是一个预先配置的对话框。它与 Windows 操作系统的“打开文件”对话框相同。该控件是从 CommonDialog 类继承的。在基于 Windows 的应用程序中,可该组件实现简单的文件选择,而不必配置自己的对话框。利用标准的 Windows 对话框,可以创建用户所熟悉的应用程序界面。
Filter 属性:获取或设置当前文件名过滤字符串,该字符串决定对话框的“文件类型”框中出现的选择内容。对于每个过滤选项,过滤字符串都包含过滤条件说明,后接一垂直线条(|)和过滤模式。不同过滤选项的字符串由垂直线条隔开。
例如:“Text files (.txt)|.txt|All files (.)|.”。如果要将多个过滤模式添加到过滤条件中,可用分号将文件类型分隔开,例如:
"Image Files(.BMP;.JPG;.GIF)|.BMP;.JPG;.GIF|All files (.)|."使用 FilterIndex 属性设置第一个显示给用户的过滤选项。
OpenFile() 方法:打开用户选定的具有只读权限的文件,该文件由 FileName 属性指定。
使用该方法可从对话框以只读方式快速打开文件。
“打开图片”(button1)按钮绑定事件:
private void button1_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "@.Jpg|*.jpg|@.Png|*.png|@.Gif|*.gif|@.All files|*.*";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
FileStream fs = new FileStream(filePath = openFileDialog1.FileName, FileMode.Open, FileAccess.Read);
//通过调用系统的画笔工具,画出一个Image类型的数据,传给pictureBox。
Image im = System.Drawing.Bitmap.FromStream(fs);
PicSource.Image = im;
this.PicSource.SizeMode = PictureBoxSizeMode.Zoom;
}
}
记录鼠标点击事件,绘制红色矩形框
#region 记录鼠标点击事件
private void PicSource_MouseDown(object sender, MouseEventArgs e)
{
int originalWidth = this.PicSource.Image.Width;
int originalHeight = this.PicSource.Image.Height;
PropertyInfo rectangleProperty = this.PicSource.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
Rectangle rectangle = (Rectangle)rectangleProperty.GetValue(this.PicSource, null);
int currentWidth = rectangle.Width;
int currentHeight = rectangle.Height;
double rate = (double)currentHeight / (double)originalHeight;
int black_left_width = (currentWidth == this.PicSource.Width) ? 0 : (this.PicSource.Width - currentWidth) / 2;
int black_top_height = (currentHeight == this.PicSource.Height) ? 0 : (this.PicSource.Height - currentHeight) / 2;
int zoom_x = e.X - black_left_width;
int zoom_y = e.Y - black_top_height;
double original_x = (double)zoom_x / rate;
double original_y = (double)zoom_y / rate;
Pstart = new Point((int)original_x, (int)original_y);
start = e.Location;
Invalidate();
blnDraw = true;
}
private void PicSource_MouseMove(object sender, MouseEventArgs e)
{
if (blnDraw)
{
if (e.Button != MouseButtons.Left)//判断是否按下左键
return;
Point tempEndPoint = e.Location; //记录框的位置和大小
rect.Location = new Point(
Math.Min(start.X, tempEndPoint.X),
Math.Min(start.Y, tempEndPoint.Y));
rect.Size = new Size(
Math.Abs(start.X - tempEndPoint.X),
Math.Abs(start.Y - tempEndPoint.Y));
//记录绘制大小
int originalWidth = this.PicSource.Image.Width;
int originalHeight = this.PicSource.Image.Height;
PropertyInfo rectangleProperty = this.PicSource.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
Rectangle rectangle = (Rectangle)rectangleProperty.GetValue(this.PicSource, null);
int currentWidth = rectangle.Width;
int currentHeight = rectangle.Height;
double rate = (double)currentHeight / (double)originalHeight;
int black_left_width = (currentWidth == this.PicSource.Width) ? 0 : (this.PicSource.Width - currentWidth) / 2;
int black_top_height = (currentHeight == this.PicSource.Height) ? 0 : (this.PicSource.Height - currentHeight) / 2;
int zoom_x = e.X - black_left_width;
int zoom_y = e.Y - black_top_height;
double original_x = (double)zoom_x / rate;
double original_y = (double)zoom_y / rate;
Orect.Location = new Point(
Math.Min(Pstart.X, (int)original_x),
Math.Min(Pstart.Y, (int)original_y));
Orect.Size = new Size(
Math.Abs(Pstart.X - (int)original_x),
Math.Abs(Pstart.Y - (int)original_y));
PicSource.Invalidate();
}
}
private void PicSource_MouseUp(object sender, MouseEventArgs e)
{
blnDraw = false; //结束绘制
Bitmap bitmap = PartDraw(PicSource.Image, Orect);
this.pictureBox1.Image = bitmap;
this.pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
}
private void PicSource_Paint(object sender, PaintEventArgs e)
{
if (blnDraw)
{
if (PicSource.Image != null)
{
if (rect != null && rect.Width > 0 && rect.Height > 0)
{
e.Graphics.DrawRectangle(new Pen(Color.Red, 3), rect);//重新绘制颜色为红色
}
}
}
}
#endregion
旋转
注意!!!
button2_click_1绑定的是button2按钮
public static Bitmap KiRotate(Bitmap bmp, float angle, Color bkColor)
{
int w = bmp.Width + 2;
int h = bmp.Height + 2;
PixelFormat pf;
if (bkColor == Color.Transparent)
{
pf = PixelFormat.Format32bppArgb;
}
else
{
pf = bmp.PixelFormat;
}
Bitmap tmp = new Bitmap(w, h, pf);
Graphics g = Graphics.FromImage(tmp);
g.Clear(bkColor);
g.DrawImageUnscaled(bmp, 1, 1);
g.Dispose();
GraphicsPath path = new GraphicsPath();
path.AddRectangle(new RectangleF(0f, 0f, w, h));
Matrix mtrx = new Matrix();
mtrx.Rotate(angle);
RectangleF rct = path.GetBounds(mtrx);
Bitmap dst = new Bitmap((int)rct.Width, (int)rct.Height, pf);
g = Graphics.FromImage(dst);
g.Clear(bkColor);
g.TranslateTransform(-rct.X, -rct.Y);
g.RotateTransform(angle);
g.InterpolationMode = InterpolationMode.HighQualityBilinear;
g.DrawImageUnscaled(tmp, 0, 0);
g.Dispose();
tmp.Dispose();
return dst;
}
/
Bitmap robitmap;
bool isrotate = false;
private void button2_Click_1(object sender, EventArgs e)
{
var value = this.trackBar1.Value;
var bmp = new Bitmap(PicSource.Image);
if (!isrotate)
{
robitmap = bmp;
isrotate = true;
}
var newBmp = KiRotate(robitmap, value, Color.Transparent);
PicSource.Image = newBmp;
}
裁剪图片
public static Bitmap PartDraw(Image src, Rectangle cutpart)//切割图片
{
Bitmap rectbmp = new Bitmap(cutpart.Width, cutpart.Height, PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(rectbmp))
{
g.DrawImage(src, new Rectangle(0, 0, cutpart.Width, cutpart.Height), cutpart, GraphicsUnit.Pixel);
g.Dispose();
}
return rectbmp;
}
注意!!
下面的button2_click绑定的是saveImg按钮
保存图片
private void button2_Click(object sender, EventArgs e)
{
saveFileDialog1.Filter = "JPeg Image|*.jpg|Bitmap Image|*.bmp|Gif Image|*.gif";
saveFileDialog1.Title = "Save an Image File";
saveFileDialog1.ShowDialog();
if (saveFileDialog1.FileName != "")
{
// 通过由OpenFile方法创建的FileStream保存图像。
System.IO.FileStream fs =
(System.IO.FileStream)saveFileDialog1.OpenFile();
//根据以下内容将图像保存为适当的ImageFormat:
//在对话框中选择的文件类型。
//请注意,FilterIndex属性是基于一的。
switch (saveFileDialog1.FilterIndex)
{
case 1:
this.pictureBox1.Image.Save(fs,
System.Drawing.Imaging.ImageFormat.Jpeg);
break;
case 2:
this.pictureBox1.Image.Save(fs,
System.Drawing.Imaging.ImageFormat.Bmp);
break;
case 3:
this.pictureBox1.Image.Save(fs,
System.Drawing.Imaging.ImageFormat.Gif);
break;
}
textBox1.AppendText("图片已保存至:"+ "E:\\小白人" + "\n");
textBox1.ScrollToCaret();
fs.Close();
}
}