Free模块:
1.难点之一是纸张的对折效果
横竖对折:定义一个动态的image控件,根据当前的纸张大小设置动态image控件的边缘,然后设置定时器,让其绕着对称轴(控件的某一个边缘)旋转
撇捺对折:这种办法是行不通的,因为对称轴是对角线,而不是控件的某一个边缘: 定义一个多边形控件(三角形),设置其三个定点的位置,然后根据对折关系,让其外部的顶点逐步靠近对称点。 这种方法有个弊端,就是需要设置纸张为半透明才能看到效果
1.难点之一是纸张的对折效果
横竖对折:定义一个动态的image控件,根据当前的纸张大小设置动态image控件的边缘,然后设置定时器,让其绕着对称轴(控件的某一个边缘)旋转
撇捺对折:这种办法是行不通的,因为对称轴是对角线,而不是控件的某一个边缘: 定义一个多边形控件(三角形),设置其三个定点的位置,然后根据对折关系,让其外部的顶点逐步靠近对称点。 这种方法有个弊端,就是需要设置纸张为半透明才能看到效果
2.屏幕触控手势的辨别是通过Silverlight for windows phone Toolkit的GestureListener对象加入对手势的监听,通过控件的RenderTransform类实现随手势的各种变化
3.颜色选择器:使用的是Coding4Fun工具包(一个开源项目)中的六边形颜色选择器控件
4.分享接口:本来是用一个开源的精简版SDK——Alexis.WindowsPhone.Social.dll(它将各个新浪、腾讯、人人网三个平台提供的Windows Phone SDK综合),提供了授权、绑定账号等功能,另外还用到了popup弹出框。
5.独立存储: 手机为每个应用程序预留的空间,通常用来存储应用程序的数据和配置文件
存入:string fileName = "Scrawl_" + time.Year.ToString() + time.Month.ToString() + time.Day.ToString() + time.Hour.ToString() + time.
Minute.ToString() + time.Second.ToString() + ".jpg";
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
3.颜色选择器:使用的是Coding4Fun工具包(一个开源项目)中的六边形颜色选择器控件
4.分享接口:本来是用一个开源的精简版SDK——Alexis.WindowsPhone.Social.dll(它将各个新浪、腾讯、人人网三个平台提供的Windows Phone SDK综合),提供了授权、绑定账号等功能,另外还用到了popup弹出框。
5.独立存储: 手机为每个应用程序预留的空间,通常用来存储应用程序的数据和配置文件
存入:string fileName = "Scrawl_" + time.Year.ToString() + time.Month.ToString() + time.Day.ToString() + time.Hour.ToString() + time.
Minute.ToString() + time.Second.ToString() + ".jpg";
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
IsolatedStorageFileStream fs = store.CreateFile(fileName); //直接存放在独立存储的根部,采用关键字+时间 命名
Extensions.SaveJpeg(App.final, fs, App.final.PixelWidth, App.final.PixelHeight, 0, 100);
fs.Close();
}
读出: string[] filename;
}
读出: string[] filename;
IsolatedStorageFile stor = IsolatedStorageFile.GetUserStoreForApplication(); //进入独立存储
filename = stor.GetFileNames("Scrawl_*"); //获取独立存储区根处的文件名称,包含Scrawl关键字
for (int i = 0; i < filename.Length; i++)
{
BitmapImage src = new BitmapImage();
IsolatedStorageFileStream fs = stor.OpenFile(filename[i], FileMode.Open, FileAccess.Read); //取得文件流
src.SetSource(fs); //src即为独立存储中的图片文件
}
6.裁剪原理:用一个Polyline控件追踪并显示触屏痕迹线,画完线后,用多边形控件来表示此触屏的闭合区域,然后通过writeablebitmap的Render方法将多边形控件截图到writeablebitmap中 展开则是根据对折的顺序依次逆序做对称
7.枢轴控件Pivot:PivotItem定义每个标签 arts show模块
8.在按钮状态里使用到了expression blend工具,定义好每个按钮在点击和未被点击时呈现的状态
通过CameraTask调用摄像头,通过PhotoChooserTask调用图库选择照片
8.在添加小元素时 每个小元素认为成是一个image控件 所有的小元素都放到一个链表里 利用writeablebitmap.render方法将小元素直接放到纸张上 因为有很多种小元素图样 如果一次放多个小元素的话,需要记录每个小元素的位移和拖动放大。
PapercutWorld模块
进度条: 如果想在“处理图像”(记作任务A)的同时还要“显示进度条”(记作任务B),额外开启一个子线程去执行两个任务之一是必然的。但是,谁放在主线程中执行,谁又呆在子线程中呢?经过我反复实验表明:需要把显示进度条的任务B放在主线程中,而你原本想要完成的图像处理任务A则得受点委屈进入到子线程中运行。倘若颠倒过来,则会出现“显示进度条”的任务B被“处理图像”的任务A掩盖起来的现象,也就是说:进度条根本显示不出来!
把阳刻开启为一个线程,进度条的实现中使用了委托机制,因为涉及到了用自己创建的非主线程(new Thread(new ThreadStart(Yangke_thread)))来控制用户控件(progressbar)的显示。
普通的素描图只是简单边缘提取
其实阳刻类似于生成图像的素描效果,其算法的流程是:
灰度处理→反色处理→高斯模糊→设置阈值(小于某个值)变为红→加边框生成剪纸图→两次膨胀,两次腐蚀
阴刻
流程前大部分跟阳刻相同,只是在最后设置阈值时是置为反色(大于某个值置为红), 然后做两次腐蚀无膨胀
人像
前后做了几次开闭运算 然后中间做了一次中值滤波
关于Azure
7.枢轴控件Pivot:PivotItem定义每个标签 arts show模块
8.在按钮状态里使用到了expression blend工具,定义好每个按钮在点击和未被点击时呈现的状态
通过CameraTask调用摄像头,通过PhotoChooserTask调用图库选择照片
8.在添加小元素时 每个小元素认为成是一个image控件 所有的小元素都放到一个链表里 利用writeablebitmap.render方法将小元素直接放到纸张上 因为有很多种小元素图样 如果一次放多个小元素的话,需要记录每个小元素的位移和拖动放大。
PapercutWorld模块
进度条: 如果想在“处理图像”(记作任务A)的同时还要“显示进度条”(记作任务B),额外开启一个子线程去执行两个任务之一是必然的。但是,谁放在主线程中执行,谁又呆在子线程中呢?经过我反复实验表明:需要把显示进度条的任务B放在主线程中,而你原本想要完成的图像处理任务A则得受点委屈进入到子线程中运行。倘若颠倒过来,则会出现“显示进度条”的任务B被“处理图像”的任务A掩盖起来的现象,也就是说:进度条根本显示不出来!
把阳刻开启为一个线程,进度条的实现中使用了委托机制,因为涉及到了用自己创建的非主线程(new Thread(new ThreadStart(Yangke_thread)))来控制用户控件(progressbar)的显示。
普通的素描图只是简单边缘提取
这种算法通过灰度信息分布来控制素描图像的细节特征, 通过灰度合成得到图像边缘特征的加强和柔化,
形成素描效果.
首先得到输入图像的灰度反色图, 并对其进行高斯模糊滤波,平滑边缘特征,然后采用灰度合成将滤波后的反色图和输入图像的灰度图进行合成, 并同时起到对混合的图像的亮度进行自适应调整的作用,
形成图像素描艺术风格。
这种 算法在突出边缘特征的同时, 能够较好地保持输入图像的细节特征,
并实现素描效果.
为了实现真实的素描效果, 就要使图像中物体轮廓清晰地显示出来, 其他非重要部分可用模糊方式表示, 并去除影响效果的噪声. 通过利用高斯滤波对图像进行处理, 可以实现素描绘画中自然柔和的风格,
并提高最终效果的质量.
高斯滤波是根据高斯分布规律对目标像素周围像素进行加权平均来得到目标像素的新值.
高斯滤波是根据高斯分布规律对目标像素周围像素进行加权平均来得到目标像素的新值.
其实阳刻类似于生成图像的素描效果,其算法的流程是:
灰度处理→反色处理→高斯模糊→设置阈值(小于某个值)变为红→加边框生成剪纸图→两次膨胀,两次腐蚀
阴刻
流程前大部分跟阳刻相同,只是在最后设置阈值时是置为反色(大于某个值置为红), 然后做两次腐蚀无膨胀
人像
前后做了几次开闭运算 然后中间做了一次中值滤波
关于Azure
默认的用户名和密码存储在独立存储的一个文件里 每次读取默认的用户名
利用azure的mobile services建立一个TodoItem table 里面存储用户名及其分数
然后查询数据表,将用户的分数进行排名,显示用户的排名,并将其中的前十名筛选出来,显示在排行榜页面上
//将用户名(user.Text)和得分(App.appscore)插入另一个表——todoItem
var todoitem = new TodoItem { Name = user.Text, Score = App.appscore };
items.Add(todoitem);
await todoTable.InsertAsync(todoitem); //此时已插入完成,然后可以进行分数的排名了
MessageBoxResult m = MessageBox.Show("Successfully logined! Submit your score and view the leaderboard?", "Notice", MessageBoxButton.OKCancel);
if (m == MessageBoxResult.OK)
{
helpitem = new List<ClsItem>();
App.TopItem = new List<ClsItem>();
//排名,先选前10名
for (int n = 0; n < items.Count; n++)
{
ClsItem hlp = new ClsItem();
hlp.id = items[n].Id;
hlp.score = items[n].Score;
hlp.name = items[n].Name;
helpitem.Add(hlp);
} //另外复制到一个数据结构里去排序
select(); //此时topItem哩存储的是前十名的记录
for (int n = 0; n < App.TopItem.Count; n++)
{
if (App.TopItem[n].name == user.Text&&App.TopItem[n].score==App.appscore)
{
App.place = n+1; //此用户的名次
break;
}
}
关于排行榜页面,默认显示是上次刷新的结果(每次存在独立存储里,然后读),当用户点刷新按钮时才显示此次比较的结果