WPF头像裁剪

2017-06-27 12:20:21来源:CSDN作者:leebin_20人点击

需求很常见,就是用户上传头像前进行固定大小的裁剪。
百度一番,找到几个差不多的,
其一 http://download.csdn.net/detail/tianhaosen/7159901,这个的实现方式是截图框大小固定不变,背景图可以通过鼠标拖动和鼠标滚轮缩放,经过测试,这个对图片的裁剪不是很准确,尤其是大图或者靠近图片边缘裁剪的时候会出现较大误差,然后我尝试调整了下截图位置的算法,但多少还是有偏差,无奈只好放弃,有兴趣的同学可以下下来研究研究。
其二 http://blog.csdn.net/jtl309/article/details/50651911,这个的实现方式是背景图片保持大小不变,裁剪框可以通过鼠标拖动进行缩放。于是尝试在这个的基础上进行调整:)
首先,裁剪框的拖动以及缩放作者已经做的很完善了,主要是利用了Thumb控件进行自定义。我的需求是裁剪框要是一个固定大小的正方形,所以我对作者的源码进行了修改。源码中作者是在DragHelperBase.cs中对矩形框的大小进行实时计算,其中有4个ResizeFrom**方法,我在这4个方法的入参中均加入了宽高(out double HeightNew,out double WidthNew),并且在方法的最后一行赋值高和宽相等,这样就保证了裁剪框始终是正方形。ok,算法代码修改完毕,下面就是对样式代码进行了一些调整,这个各位同学根据自己需求改动即可。

现在回到我们自己的项目,把上面修改过的工程生成的dll引用进来,

<Canvas x:Name="canvas" Grid.Row="1" Width="500" Height="500">            <Rectangle Stroke="{StaticResource ButtonBackgroundBrush}"                        Fill="Transparent" StrokeThickness="2"                        Width="300" Height="300" Canvas.Left="100" Canvas.Top="100"                       UICommon:DragControlHelper.IsEditable="True"                        UICommon:DragControlHelper.IsSelectable="True"/>            <UICommon:DragControlHelper CornerWidth="6" Background="{StaticResource CancleButtonBackgroudBrush}" BorderBrush="{StaticResource ButtonBackgroundBrush}" DragChanging="DragControlHelper_DragChanging" DragCompleted="DragControlHelper_DragCompleted"/> </Canvas><StackPanel Grid.Row="2" HorizontalAlignment="Center" Orientation="Horizontal">            <Button Content="取消" Name="btnCancel" Width="62" Height="32"  Foreground="#FFFFFF" Style="{StaticResource CustomButtonStyle}"                        Margin="10" Click="btnCancel_Click" Background="{StaticResource CancleButtonBackgroudBrush}"></Button>            <Button Content="确定" Name="btnConfirm" Width="62" Height="32"  Foreground="#FFFFFF" Style="{StaticResource CustomButtonStyle}"                        Margin="10" Click="btnConfirm_Click" Background="{StaticResource ButtonBackgroundBrush}"></Button></StackPanel>
private void DragControlHelper_DragCompleted(object Sender, UICommon.Controls.DragChangedEventArgs e){            newBound = e.NewBound;//拖动完成后的新位置}private void btnConfirm_Click(object sender, RoutedEventArgs e){            Bitmap map = new Bitmap(choosedImagePath);            int mapHeight = map.Height;            int mapWidth = map.Width;//图片宽高            int actualHeight = 0;            int actualWidth = 0;//Canvas宽高            int offset = 1;            int left = 0;            int top = 0;            int x = (int)newBound.X;            int y = (int)newBound.Y;            if (mapHeight>mapWidth)//此时高度撑满500            {                actualHeight = 500;                actualWidth = 500 * mapWidth / mapHeight;                left = (500 - actualWidth) / 2;                x -=  left;                offset = mapHeight / 500d;//需要小数            }            else//此时宽度撑满500            {                actualWidth = 500;                actualHeight = 500 * mapHeight / mapWidth;                top = (500 - actualHeight) / 2;                y -= top;                offset = mapWidth / 500d;            }            //计算截图位置和大小            int w= (int)Math.Round(newBound.Width * offset, MidpointRounding.AwayFromZero);            int h = (int)Math.Round(newBound.Height * offset, MidpointRounding.AwayFromZero);            int startX=(int)Math.Round( x * offset,MidpointRounding.AwayFromZero);            int startY=(int)Math.Round( y * offset,MidpointRounding.AwayFromZero);            var resultMap = KiCut(map,startX,startY, w, h);            if (resultMap==null)            {                Alert alert = new Alert("图片裁剪失败,请重新选择图片。");                alert.Owner = this;                alert.ShowDialog();                return;            }            string savePath = NIM.ToolsAPI.GetLocalAppDataDir() + ConfigHelper.GetSettingStr("appDataDir") + "//CutImageTemp//";            if (!Directory.Exists(savePath))            {                Directory.CreateDirectory(savePath);            }            string name = "UserHead_" + DateTimeHelper.DatetimeConvertUnix() + ".jpg";            string path=savePath + name;            if (resultMap.Width!=300)//用户调整了裁剪框大小            {                Bitmap newImage = new Bitmap(300, 300, System.Drawing.Imaging.PixelFormat.Format24bppRgb);                Graphics g = Graphics.FromImage(newImage);                g.DrawImage(resultMap, 0, 0, 300, 300);                g.Dispose();                newImage.Save(path, ImageFormat.Jpeg);            }            else//直接保存            {                resultMap.Save(path, ImageFormat.Jpeg);            }}private static Bitmap KiCut(Bitmap b, int StartX, int StartY, int iWidth, int iHeight){            if (b == null)            {                return null;            }            try            {                Bitmap bmpOut = new Bitmap(iWidth, iHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);                Graphics g = Graphics.FromImage(bmpOut);                g.DrawImage(b, new System.Drawing.Rectangle(0, 0, iWidth, iHeight), new System.Drawing.Rectangle(StartX, StartY, iWidth, iHeight), GraphicsUnit.Pixel);                g.Dispose();                return bmpOut;            }            catch(Exception ex)            {                return null;            }}private void Window_Loaded(object sender, RoutedEventArgs e){            BinaryReader binReader = new BinaryReader(File.Open(choosedImagePath, FileMode.Open));            FileInfo fileInfo = new FileInfo(choosedImagePath);            byte[] bytes = binReader.ReadBytes((int)fileInfo.Length);            binReader.Close();            bitmap = new BitmapImage();            bitmap.BeginInit();            bitmap.StreamSource = new MemoryStream(bytes);            bitmap.EndInit();            ImageBrush brush = new ImageBrush(bitmap);            brush.Stretch = Stretch.Uniform;            this.canvas.Background = brush;}

稍微解释下代码,以上代码只是核心部分,另外newBound在构造函数中需要初始化new Rect(100, 100, 300, 300),因为我这边需要裁剪成300X300的图片,并且我在窗口的Load事件里给Canvas设置了背景图片,也就是用户选择的图片(路径存放在choosedImagePath变量中),并且设置其Stretch属性为Uniform,这样能保证图片在框中自适应正常显示。
虽然我这边默认框大小是300X300,但是一旦用户缩放了裁剪框,我们就需要对裁剪下来的图片进行放大或压缩,然后再做进一步操作(如转码base64、上传至服务器)。

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台