在开始编写自己的图像裁剪控件之前,通常会花费大量时间和精力在网络上搜索现有的控件,但这次没有这样做,因为几乎可以肯定找不到符合期望的现成控件。因此,决定立即开始自己开发。想要的是一个能够显示图像的控件,并且可以调整选择矩形等。
控件基于标准的Panel控件,这样它就继承了所有Panel的属性和行为,使得设计和布局表单变得更加简单。
控件的使用非常简单,但有几个属性是值得了解的。这些属性大多与控件的外观有关。
Image - 可以通过这个属性分配需要裁剪的图像。
OverlayColor - 未选中的图像部分会显示半透明的覆盖层,以便更容易看到选择区域。可以在这里设置覆盖层的颜色。
OverlayAlpha - 覆盖层是半透明的,OverlayAlpha属性决定了它的透明度。值应该在0(不可见)到255(完全不透明)之间。
SelectionInitialMode - 确定加载图像时自动显示的选择区域。如果不喜欢标准模式并选择Custom,应该确保在代码中处理SetInitialSelection事件。否则,将使用FullImage模式。
SelectionResizeMode - 确定如何选择区域的调整方式。它还决定了是否显示角落的调整手柄。
SelectionBorderColor, SelectionBorderDashStyle, SelectionBorderDashPattern 和 SelectionBorderWidth 都决定了如何选择区域周围的边框是如何绘制的。
SelectionResizeHandleBorderColor, SelectionResizeHandleBorderWidth 和 SelectionResizeHandleColor 决定了角落的调整手柄是如何绘制的(如果需要绘制的话)。
ThumbnailScalingPercentage - 控件可以为裁剪的图像生成缩略图。这个属性决定了它应该有多大,以完整图像大小的百分比来表示。
StartEditingMode - 确定何时可以编辑图像。
GetCroppedImage - 返回控件中裁剪到选定区域的图像。
GetCroppedImageThumbnail - 返回控件中裁剪到选定区域的图像的缩略图。也请参考ThumbnailScalingPercentage属性。
StartEdit 和 EndEdit - 调用这些方法开始或结束编辑模式。
SaveCroppedImage - 直接将裁剪后的图像保存到文件。
SaveCroppedImageThumbnail - 直接将裁剪后的图像缩略图保存到文件。
ResetSelection - 将选择区域重置为初始选择。
如上所述,使用控件非常简单直接。只需将其拖放到表单上,调整大小和外观以符合喜好。然后,可以像这样为Image属性分配一个图像:
cropBox1.Image = Image.FromFile(fileName);
之后,可以编辑选择区域,当准备好裁剪图像时,可以像这样获取裁剪后的图像:
Image croppedImage = cropBox1.GetCroppedImage();
之后,使用.NET编程将图像保存为Jpeg文件就变得非常简单:
croppedImage.Save(fileName, ImageFormat.Jpeg);
提示:控件使用整个客户端表面来绘制图像,但如果不喜欢这种外观,可以简单地设置Padding属性来获得图像周围的边框。
标准的.NET功能加载图像文件时(如上代码所示)并不关心EXIF方向标签。这意味着如果使用智能手机等拍摄的照片,加载到Image类中时可能会完全显示错误。
幸运的是,这个问题很容易修复,当然已经将其整合到控件中:
if (Array.IndexOf(_image.PropertyIdList, 274) > -1)
{
var orientation = (int)_image.GetPropertyItem(274).Value[0];
switch (orientation)
{
case 1:
// No rotation required.
break;
case 2:
_image.RotateFlip(RotateFlipType.RotateNoneFlipX);
break;
case 3:
_image.RotateFlip(RotateFlipType.Rotate180FlipNone);
break;
case 4:
_image.RotateFlip(RotateFlipType.Rotate180FlipX);
break;
case 5:
_image.RotateFlip(RotateFlipType.Rotate90FlipX);
break;
case 6:
_image.RotateFlip(RotateFlipType.Rotate90FlipNone);
break;
case 7:
_image.RotateFlip(RotateFlipType.Rotate270FlipX);
break;
case 8:
_image.RotateFlip(RotateFlipType.Rotate270FlipNone);
break;
}
// This EXIF data is now invalid and should be removed.
_image.RemovePropertyItem(274);
}