在今天的吹牛节目开始之前,先交代一件事:

关于玩WP 8.1开发所使用的VS版本问题。对版本的要求是2013的Update2,这是最低要求,只要是这个版本或以上都可以,而update3,update4,update5是不是必须更新呢?不是的,VS的update是可选的,而且每个update都会累积,所以,update越多,安装包的体积越大。因此,WP开发我们只需update2就行了,我用的也是u2。如果你觉得MSDN原版不好下,可以从下面的地址下,我已经把相关的.iso上传到115。这里面是旗舰版。

开发工具
115网盘礼包码:5lbblgv09y6k
http://115.com/lb/5lbblgv09y6k

如果你还没有安装VS,我这里分享一个小技巧。就是在安装时,不要勾选Windows Phone 8.0 SDK,安装后就没有8.0的模拟器和镜像,也不能开发8.0的应用,只能开发8.1的,而且只能用真机调试。

安装后,你再下载我上面分享的另一个.iso——windowsphone81sdkupdate1.iso,这里不仅包含8.1的SDK,还带了8.1 Update 1的模拟器,即有“小娜”的版本。

如此一来,你只安装了最新的8.1模拟器,而没有8.0的模拟器了。当然如果你要开发8.0的应用,就要安装Windows Phone 8.0 SDK,我上面说的当你只开发8.1应用的时候用的。

=======================================================

好了,吹牛节目正式开始,由于剧组缺钱,本节目的主持人只有老周一人,没有后台工作人员,有点像关老爷单刀赴会的感觉。今天咱们吹一下如何进行图像处理,比如怎么把图片变成灰度、反色、黑色等。

老周不是专业搞图像的,老周是打酱油专业毕业的,所以老周不懂相关的知识,但不要紧,只要我们好好利用现有的API,也可以对图像进行一些非专业性处理。我们可以不明白图像文件的具体结构,只要懂得如何改写像素数据就行了。

要弄清楚像素数据是如何排列的,首先要简单理解一下常见的像素格式是啥样的。这些格式由Windows.Graphics.Imaging.BitmapPixelFormat枚举定义,Unknown成员不管它,我们只关心另外三个。

Bgra8——最后面的8表示8位,即每个颜色值占8位,也就是1字符,bgra,第一个字节表示B(蓝)的值,第二个字节表示G(绿)的值,第三个字节表示R(红)的值,第四个字节表示A(不透明度)的值。举个例子,假设有一个图片里面有四个像素,宽为2,高为2,即两行两列。结构如下表所示:

R = 100

G = 0

B = 200

A = 255

R = 255

G = 50

B = 32

A = 255

R = 12

G = 30

B = 90

A = 255

R = 120

G = 60

B = 75

A = 255

像素数据是一个字符数组,比如上面的2*2的图像,转换为像素数据为:

{
200, 0, 100, 255, 32, 50, 255, 255 …… 75, 64, 120, 255
}

因为像素格式为bgra,所以排第一的是B的值,接着是G,然后是R,最后是A,也就是说,每四个字节表示一个像素点,上述例子中,图像有四个像素点,每个点由4个字节表示,所以整个图像的像素数据共4*4=16字节。

字节的排列就是按像素点顺序排放的,从左到右,从上到下,先排完第一行,再排第二行,第三行……一直排到最后一个像素点。

Rgba8……和上面的一样,每个颜色值占一个字节,只是排列时顺序不同,rgba是最常用的,因为这样排列图像不会偏色,即第一个字节是R,第二个字节是G,第三个字节是B,最后是A。这个RGB的通道不同顺序产生的不同效果,大家可以在PS里面查看,PS中“图层”窗口中有个“通道”面板,那里可以看到各个通道的效果。

Rgba16——和上面一样,排列顺序也是R -> G -> B -> A,但是,rgba16中每个色值为16位,即占用2个字节。在像素数据中,第一个和第二个字节共同表示R值;第三个,第四个字节共同表示G的值;第五个第六个字节为B的值,第七、八个字节表示A。这个模式很少用,因为不太好套公式,呵呵。

理论知识还是抽象的,咱们来干点实事吧。下面老周给大家演示两个比较简单的处理——灰度 和 反色。

图像处理的各种方法大家可以查书,可以网上查,反正都有固定公式的。

1、灰度处理。

这里我选用平均法,即把每个像素点中R,G,B三个值进行相加,然后除以3,再把这个平均后的值替换原来的R,G,B值,A是不透明度,一般可以不管它,生成新的像素数据值时A值就用原图的A值就行了,主要是针对RGB进行计算。代码如下:

        /// <summary>
/// 灰度处理
/// </summary>
private byte[] GrayScale(byte[] rgbaBuff)
{
byte[] resbytes = new byte[rgbaBuff.Length];
for (int i = ; i < rgbaBuff.Length; i += )
{
byte r = rgbaBuff[i];
byte g = rgbaBuff[i + ];
byte b = rgbaBuff[i + ];
byte a = rgbaBuff[i + ];
// 使用平均法
byte ev = Convert.ToByte((Convert.ToDouble(r) + Convert.ToDouble(g) + Convert.ToDouble(b)) / 3d);
// 生成新的像素值
resbytes[i] = resbytes[i + ] = resbytes[i + ] = ev;
resbytes[i + ] = a;
}
return resbytes;
}

我的示例都是用rgba8格式的,每个像素点需要4个字节,所以在for循环中,i的境量不是i++,而是i += 4,即每次循环跳4个字节,这样才能保证每一轮循环都访问一个像素点。

2、反色。

反色最简单,分别用255去減RGB三个值就行了,即

newR = 255 - oldR, newG= 255 - oldG, newB= 255-oldB

        /// <summary>
/// 反色
/// </summary>
private byte[] InvertPixels(byte[] rgbaBuff)
{
byte[] res = new byte[rgbaBuff.Length];
for (int i = ; i < rgbaBuff.Length; i += )
{
byte r = rgbaBuff[i];
byte g = rgbaBuff[i + ];
byte b = rgbaBuff[i + ];
byte a = rgbaBuff[i + ];
// 反色就是用255分别减去R,G,B的值
res[i] = (byte)( - r);
res[i + ] = (byte)( - g);
res[i + ] = (byte)( - b);
res[i + ] = a;
}
return res;
}

3、获取源图像的像素数据。

要得到源图像的像素数据,需要先对图像进行解码,这个应该很多观众都会,就是用Windows.Graphics.Imaging.BitmapDecoder类来解码。

我建议大家通过帧来获取单帧图像的像素数据,一般来说,静态图片只有一帧,所以调用BitmapDecoder实例的GetFrameAsync(0)方法就能得到第一帧的图像,由BitmapFrame类封装,再通过BitmapFrame实例的GetPixelDataAsync方法得到一个PixelDataProvider实例,再访问PixelDataProvider实例的DetachPixelData方法就能得到表示像素数据的字节数组。

        enum OperType { Gray, Invert };

        private async Task<BitmapSource> ImageToProcAsync(IRandomAccessStream inputStream, OperType opt)
{
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(BitmapDecoder.JpegDecoderId, inputStream);
// 获取第一帧
BitmapFrame frame = await decoder.GetFrameAsync();
// 获取像素数据
PixelDataProvider pixprd = await frame.GetPixelDataAsync(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Straight, new BitmapTransform(), ExifOrientationMode.IgnoreExifOrientation, ColorManagementMode.DoNotColorManage);
byte[] data = pixprd.DetachPixelData();
// 处理
byte[] returnData = null;
if (opt == OperType.Gray)
{
returnData = GrayScale(data);
}
else
{
returnData = InvertPixels(data);
}
// 创建新的位图对象
WriteableBitmap wb = new WriteableBitmap((int)frame.PixelWidth, (int)frame.PixelHeight);
// 复制数据
returnData.CopyTo(wb.PixelBuffer);
return wb;
}

OperType是自定义枚举,Gray表示灰度处理,Invert表示反色处理。

最后,请各位观众一起看看效果吧。

     

各位观众,感谢您收看由火星电视台转播的老周吹牛节目,本集示例的源代码稍后给出下载地址。Thank you.

示例下载:http://files.cnblogs.com/tcjiaan/imgProcSampleApp.zip

欢迎下个世纪同一时间,准时收看老周吹牛特别节目。本节目由火星移动有限公司独家赞助。

88。

【WP 8.1开发】How to 图像处理的更多相关文章

  1. 【VS开发】【图像处理】GigE和USB3 vision选择?

    [VS开发][图像处理]GigE和USB3 vision选择? 具体得看你现场的应用吧,如 现场需要的工作距离,网线可达到100m以内,USB3.0一般般的5m以内: GigE双端都有卡扣,保证了与相 ...

  2. 【WP 8.1开发】电子罗盘

    罗盘,估计也不用我过多介绍,学过初中物理的都知道,不管是指南针,还是指北针,其本质就是用来辨别方向的. 操作电子罗盘伟感器也不复杂,主要就是两个角度: 1.当前方向与磁北的夹角: 2.当前方向与地北的 ...

  3. 【WP 8.1开发】解决调用真实摄像头会死机的问题

    无论你是用Silverlight还是用RT的API来开发,在使用MediaCapture拍照片或录视频时,要是在模拟器上运行会万事大吉:但是,一旦放到真实手机上运行,肯定有人发现了,细心的朋友肯定发现 ...

  4. 【WP 8.1开发】文件选取器的使用方法

    在以往的WP7x/8.0开发中,我们使用选择器可以浏览并打开图片.音频.视频等一些特殊文件,在8.0 SDK中的运行时API(从Win 8 app中移植)尽管提供了Windows.Storage.Pi ...

  5. 【WP 8.1开发】如何把自定义字体塞进应用里

    或许,系统自带的字体不足以体现应用程序的魅力,对于表现极强的汉字来说,更是如此.这时候,我们就会想,要是能把网上下载的艺术字体塞到应用包中,那岂不美哉?那么,这可以实现吗?答案是Yes的. 接下来,阿 ...

  6. 【WP 8.1开发】自定义(RAW)通知的使用

    继续前面的话题,还是推送通知.上一篇文章中遗留了RAW通知的推送没有给各位演示,特特地留到现在,不为别的,只为这个RAW通知有点意思,玩起来会比较有意思.官方文档将RAW通知译为“原始通知”,这里还是 ...

  7. 【WP 8.1开发】手机客户端应用接收推送通知

    上一篇文章中,已经完成了用于发送通知的服务器端,接下来我们就用这个服务端来测试一下. 在开始测试之前,我们要做一个接收通知的WP应用. 1.启动VS Express for Windows,新建项目, ...

  8. 【WP 8.1开发】推送通知测试服务端程序

    所谓推送通知,用老爷爷都能听懂的话说,就是: 1.我的服务器将通知内容发送到微软的通知服务器,再由通知服务器帮我转发消息. 2.那么,微软的推送服务器是如何知道我的服务器要发消息给哪台手机呢?手机客户 ...

  9. 【VS开发】【图像处理】相机中白平衡的算法模拟实现

    相机主要技术点为3A算法. 而3A算法主要指的是自动对焦(AF).自动曝光(AE)及自动白平衡(AWB).自动白平衡:根据光源条件调整图片颜色的保真程度. 网上时常有类似招聘如下的招聘信息: ---- ...

随机推荐

  1. jQuery.zTree的跳坑记录

    最近项目用到树型结构的交互,一开始并不打算选择zTree,为了项目进度我妥协了,这一妥协后果就是我进坑了,在2天的挣扎中,我终于跳出坑了,活了下来,有一些感慨纪录下来. 有一个业务场景需要2个树型结构 ...

  2. 【转】request.getServletPath()和request.getPathInfo()用法

    转自:https://my.oschina.net/sub/blog/182408 在 Web 中,我们通常需要获取 URL 相对于 Webapp 的路径,主要是下面的几个方法: request.ge ...

  3. 网络流dinic实现总结

    太羞耻了,搞了半天居然没发现自己写的不是dinic,直到被一道时限紧的题目卡掉才发现 int dfs(int now,int flow,int sum) { if(now==n) return flo ...

  4. JS中原型链继承

    当我们通过构造函数A来实现一项功能的时候,而构造函数B中需要用到构造函数A中的属性或者方法,如果我们对B中的属性或者方法进行重写就会出现冗杂的代码,同时写出来也很是麻烦.而在js中每个函数都有个原型, ...

  5. 安装Python算法库

    安装Python算法库 主要包括用NumPy和SciPy来处理数据,用Matplotlib来实现数据可视化.为了适应处理大规模数据的需求,python在此基础上开发了Scikit-Learn机器学习算 ...

  6. 解决FF浏览器无法执行window.close()脚本

    在FF浏览器中输入about:config 查找dom.allow_scripts_to_close_windows 将值改为true

  7. nodejs的实现原理和搭建服务器(动态)

    心得体会    今天是我学习的Node.js的第二天,所谓的node.js其实它是javascript编写的服务器的语言,同时它又是属于后台的框架,是一个开放性的平台. 一.相关理论知识: 我们可以用 ...

  8. ie浏览器下,get请求缓存问题

    1 使用get请求数据 1)Java代码 $.getJSON("sortShow!sortShow?time="+new Date().getTime(),function(){} ...

  9. SQl SGA 整理

    --查看诊断位置信息 select * from v$diag_info; --查看sga中内存分配信息 select * from sys.x$ksmfs; --查看内存块还剩余多少 select ...

  10. 提取bmp图片的颜色信息,可直接framebuffer显示(c版本与python版本)

    稍微了解了下linux的framebuffer,这是一种很简单的显示接口,直接写入像素信息即可 配置好的内核,会有/dev/fbn 的接口,于是想能否提前生成一个文件,比如logo.fb,里面仅包含像 ...