在 Win Phone Silverlight api 中,有一个 PhotoChooserTask 选择器,指定宽、高属性,在选择图片的时候,

可以进行裁切,代码:

PhotoChooserTask photoChooserTask = new PhotoChooserTask();
photoChooserTask.Completed += new EventHandler<PhotoResult>(photoChooserTask_Completed); // 设置 宽、高
photoChooserTask.PixelHeight = ;
photoChooserTask.PixelWidth = ;
photoChooserTask.ShowCamera = true;
photoChooserTask.Show();

在图片选择完成后,可以进行裁切:

这里模仿这个交互,在 Store app 实现类似的交互。

1、XAML 页面

1)首先放置两个 Image 控件,一个显示用户缩放、平移的手势操作,另一个显示截图完成后的结果:

<Image  x:Name="img" Stretch="UniformToFill" ManipulationMode="All"  ManipulationDelta="Image_ManipulationDelta"  RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<CompositeTransform x:Name="img_transform" CenterX="0" CenterY="0"/>
</Image.RenderTransform>
</Image> <Image x:Name="imgResult" Width="100" Height="100"/>

2)放置一个 Border 元素,他的边框为黑色透明,中间的宽、高固定为 200px,里面放一个 白色的 Border,作为取景框:

<!--屏幕遮罩 -->
<Border IsHitTestVisible="False" x:Name="borderMask" BorderThickness="135,268.3" Background="Transparent" BorderBrush="#55000000" >
<Border BorderThickness="1" BorderBrush="White"/>
</Border>

2、在 C# 页面

1)注册当前 Page 对象的 SizeChanged 事件,以当 Windows 的宽、高发生改变时,调整遮罩 和 图片的位置:

 // 当页面布局发生改变时,动态调整遮罩的位置
this.SizeChanged += PhotoChooserPage_SizeChanged;
       void PhotoChooserPage_SizeChanged(object sender, SizeChangedEventArgs e)
{
InitMask();
} // 取景框的 宽、高,img 图片控件初始的最小宽、高要大于它
public double Img_w = 200; // 取景框大小 - 作为标准
Rect measureRect; void InitMask()
{
double w = Window.Current.Bounds.Width; double h = Window.Current.Bounds.Height; if (w > Img_w && h > Img_w)
{
// 左边距
double left = (w - Img_w) / 2; // 上边距
double top = (h - Img_w) / 2; // 取景框作为截图的标准
measureRect = new Rect(left, top, Img_w, Img_w); // 把 Border 的边框设置为黑色半透明,背景为 null,则实现取景框效果
borderMask.BorderThickness = new Thickness(left, top, left, top); borderMask.Width = w;
borderMask.Height = h; Canvas.SetLeft(img, left);
Canvas.SetTop(img, top); Canvas.SetLeft(imgResult, (w - imgResult.ActualWidth) / 2);
}
}

2)在 Image 控件的 Image_ManipulationDelta 事件中,调整当前 Image 的 拉伸、缩放:

 // 缩放累加
double scale = 1.0; // 平移累加
double translate_x = ;
double translate_y = ; object o = ;
private void Image_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
e.Handled = true; lock (o)
{
// 非惯性下
if (!e.IsInertial)
{
// x-y 屏幕坐标的更改
translate_x += e.Delta.Translation.X;
translate_y += e.Delta.Translation.Y; // 两指缩放更改
scale *= e.Delta.Scale; // 更改图片 CompositeTransform 对象
img_transform.TranslateX = translate_x;
img_transform.TranslateY = translate_y; img_transform.ScaleX = img_transform.ScaleY = scale; // 如果超出取景框,则撤销上面的修改
if (!IsValide())
{ translate_x -= e.Delta.Translation.X;
translate_y -= e.Delta.Translation.Y; scale /= e.Delta.Scale; img_transform.TranslateX = translate_x;
img_transform.TranslateY = translate_y; img_transform.ScaleX = img_transform.ScaleY = scale;
}
} }
}

3)计算当前的图片范围,并限制图片的大小、边框不能在取景框里面:

  // 判断图片在遮罩的中间位置
bool IsValide()
{
Rect Temp = GetBounds(img, LayoutRoot); // 查找当前 Windows.Foundation.Rect 所表示的矩形和指定 Windows.Foundation.Rect 所表示的矩形的交集,并将结果存储为当前
// Windows.Foundation.Rect
Temp.Intersect(measureRect); if (Temp == measureRect)
{
return true;
} return false;
} // 获取 UIElement 在页面中的坐标和尺寸
public Rect GetBounds(FrameworkElement childElement, FrameworkElement parentElement)
{
// https://msdn.microsoft.com/en-us/library/system.windows.media.visual.transformtovisual%28v=vs.110%29.aspx
// https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.uielement.transformtovisual.aspx
GeneralTransform transform = childElement.TransformToVisual(parentElement); return transform.TransformBounds(new Rect(, , childElement.ActualWidth, childElement.ActualHeight));
}

4)当用户点击 ”裁切“ 按钮时, 使用 BitmapEncoder 对图像进行裁切:

        private async void AppBarButton_Crop_Click(object sender, RoutedEventArgs e)
{
appBar.IsEnabled = false; try
{
StorageFile sourceFile = PickedFile;// await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync("Images\\test\\test.jpg"); if (PickedFile == null) return; using (var readStream = await sourceFile.OpenReadAsync())
{
var decoder = await BitmapDecoder.CreateAsync(readStream); //using (InMemoryRandomAccessStream writeStream = new InMemoryRandomAccessStream())
//{ if (WriteStream != null)
{
WriteStream.Dispose();
} WriteStream = new InMemoryRandomAccessStream(); BitmapEncoder encoder = await BitmapEncoder.CreateForTranscodingAsync(WriteStream, decoder); Rect temp = GetBounds(img, LayoutRoot); double scale_x = decoder.PixelWidth / temp.Width; encoder.BitmapTransform.Bounds = new BitmapBounds
{
X = (uint)Math.Round((measureRect.X - temp.X) * scale_x, ),
Y = (uint)Math.Round((measureRect.Y - temp.Y) * scale_x, ),
Width = (uint)Math.Round(measureRect.Width * scale_x, ),
Height = (uint)Math.Round(measureRect.Height * scale_x, )
}; await encoder.FlushAsync(); BitmapImage bi = new BitmapImage();
bi.SetSource(WriteStream);
imgResult.Source = bi; // 如果需要设置图片的固定宽、高,可以使用 WriteableBitmap 对象
//WriteableBitmap wb = new WriteableBitmap(120, 120);
//wb.SetSource(writeStream);
//imgResult.Source = wb; double size = WriteStream.Size / ( * 1024.0);
if (size > )
await (new MessageDialog(string.Format("图片大于 5MB(当前{0:0.0}MB),请重新选择"))).ShowAsync(); //}
}
}
catch (Exception ex)
{
(new MessageDialog("截图区域超出边界了:" + ex.Message)).ShowAsync();
} appBar.IsEnabled = true;
}

在 Windows 上的显示效果:

在手机上的显示效果:

Demo 的下载链接(win8.1+ wp8.1)

2015/9/1 更新

  增加 PC 上的鼠标的滚轮事件,进行图片缩放。

   在 xaml 页面,给 Canvas 增加一个 事件: PointerWheelChanged="LayoutRoot_PointerWheelChanged"

        // 鼠标滚轮的缩、放
private void LayoutRoot_PointerWheelChanged(object sender, PointerRoutedEventArgs e)
{
// Detect scroll is completed with PointerWheelChanged : http://stackoverflow.com/questions/13816352/detect-scroll-is-completed-with-pointerwheelchanged //var m = e.KeyModifiers; e.Handled = true; lock (o)
{
if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse)
{
PointerPoint mousePosition = e.GetCurrentPoint(sender as Canvas);
var delta = mousePosition.Properties.MouseWheelDelta; scale *= (delta > ? 1.1 : 0.9); img_transform.ScaleX = img_transform.ScaleY = scale; // 如果超出取景框,则撤销上面的修改
if (!IsValide())
{
scale /= (delta > ? 1.1 : 0.9); img_transform.ScaleX = img_transform.ScaleY = scale;
} Debug.WriteLine(delta);
}
}
}

win10 uwp 工程代码下载

05、Windows Store app 的图片裁切(更新)的更多相关文章

  1. windows store app 读写图片

    using System; using System.Threading.Tasks; using System.Runtime.InteropServices.WindowsRuntime; usi ...

  2. Windows store app[Part 4]:深入WinRT的异步机制

    接上篇Windows store app[Part 3]:认识WinRT的异步机制 WinRT异步机制回顾: IAsyncInfo接口:WinRT下异步功能的核心,该接口提供所有异步操作的基本功能,如 ...

  3. Windows store app[Part 3]:认识WinRT的异步机制

    WinRT异步机制的诞生背景 当编写一个触控应用程序时,执行一个耗时函数,并通知UI更新,我们希望所有的交互过程都可以做出快速的反应.流畅的操作感变的十分重要. 在连接外部程序接口获取数据,操作本地数 ...

  4. 在桌面程序上和Metro/Modern/Windows store app的交互(相互打开,配置读取)

    这个标题真是取得我都觉得蛋疼..微软改名狂魔搞得我都不知道要叫哪个好.. 这边记录一下自己的桌面程序跟windows store app交互的过程. 由于某些原因,微软的商店应用的安全沙箱导致很多事情 ...

  5. Windows Store App 过渡动画

    Windows Store App 过渡动画     在开发Windows应用商店应用程序时,如果希望界面元素进入或者离开屏幕时显得自然和流畅,可以为其添加过渡动画.过渡动画能够及时地提示用户屏幕所发 ...

  6. Windows Phone App Studio发布重要更新-支持Windows 8.1 源代码生成

    自2013年8月Apps Team发布Windows Phone App Studio以来,由于其低入门门槛和较好的易用性,用户和项目数量增长迅速,从Windows Phone Developer B ...

  7. 01、Windows Store APP 设置页面横竖屏的方法

    在 windows phone store app 中,判断和设置页面横竖屏的方法,与 silverlight 中的 Page 类 不同,不能直接通过 Page.Orientation 进行设置.而是 ...

  8. Windows store app[Part 1]:读取U盘数据

    Windows 8系统下开发App程序,对于.NET程序员来说,需要重新熟悉下类库. 关于WinRT,引用一张网上传的很多的结构图: 图1 针对App的开发,App工作在系统划定的安全沙箱内,所以通过 ...

  9. Windows Store App 偏移特效

    通过前面讲解的内容,读者已经了解了如何在三维空间中使旋转对象绕指定的旋转中心旋转一定的角度.接下来在这个基础上进一步讲解如何对旋转对象进行平移.下面首先介绍一下用到的几个属性. q  LocalOff ...

随机推荐

  1. 神经网络可以拟合任意函数的视觉证明A visual proof that neural nets can compute any function

    One of the most striking facts about neural networks is that they can compute any function at all. T ...

  2. awk排序作业

    输入:给定一个hotelinfo文件,文件格式如下: shanghai_city_7208      上海全季酒店淮海路店 shanghai_city_14744     锦江之星上海金山城市沙滩店 ...

  3. iOS: FFmpeg的使用一

    现状:现在视频直播非常的火,所以在视频直播开发中,使用的对视频进行遍解码的框架显得尤为重要了,其实,这种框架蛮多的,这次主要介绍一下FFmpeg视频播放器的集成和使用,FFmpeg是视频编解码的利器. ...

  4. OpenCV学习(9) 分水岭算法(3)

    本教程我学习一下opencv中分水岭算法的具体实现方式. 原始图像和Mark图像,它们的大小都是32*32,分水岭算法的结果是得到两个连通域的轮廓图. 原始图像:(原始图像必须是3通道图像) Mark ...

  5. DICOM中的入门概念

    DICOM标准是医学影像界技术人员逃不掉的标准.本系列专题是JATI对DICOM标准的阐述,力图使PACS管理员和软件工程师都能理解. DICOM标准的提出者DICOM标准委员会是ISO组织的合作者. ...

  6. 如何为Failover Cluster添加Quorum disk

    无废话, 上图.

  7. 词向量( Distributed Representation)工作原理是什么

    原文:http://www.zhihu.com/question/21714667 4 个回答 83赞同反对,不会显示你的姓名 皮果提 刘鑫.莫教授要养猫.Starling Niohuru 等人赞同 ...

  8. sql分页性能测试结果

    --方案一: declare @d datetime set @d = getdate() ID from Info order by ID) order by ID select [not in方法 ...

  9. Google Maps API v2密钥申请以及实现地图定位导航

    注意新建项目之前需要安装 google play  services 然后导入 通过上图方法导入sdk包下面的一个包: \adt-bundle-windows-x86\sdk\extras\googl ...

  10. HDU1004——Let the Balloon Rise

    Problem Description Contest time again! How excited it is to see balloons floating around. But to te ...