【WP 8.1开发】How to 图像处理

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

关于玩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 = 0; i < rgbaBuff.Length; i += 4)
            {
                byte r = rgbaBuff[i];
                byte g = rgbaBuff[i + 1];
                byte b = rgbaBuff[i + 2];
                byte a = rgbaBuff[i + 3];
                // 使用平均法
                byte ev = Convert.ToByte((Convert.ToDouble(r) + Convert.ToDouble(g) + Convert.ToDouble(b)) / 3d);
                // 生成新的像素值
                resbytes[i] = resbytes[i + 1] = resbytes[i + 2] = ev;
                resbytes[i + 3] = 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 = 0; i < rgbaBuff.Length; i += 4)
            {
                byte r = rgbaBuff[i];
                byte g = rgbaBuff[i + 1];
                byte b = rgbaBuff[i + 2];
                byte a = rgbaBuff[i + 3];
                // 反色就是用255分别减去R,G,B的值
                res[i] = (byte)(255 - r);
                res[i + 1] = (byte)(255 - g);
                res[i + 2] = (byte)(255 - b);
                res[i + 3] = 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(0);
            // 获取像素数据
            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。

时间: 2024-10-03 23:01:06

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

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

继续前面的话题,还是推送通知.上一篇文章中遗留了RAW通知的推送没有给各位演示,特特地留到现在,不为别的,只为这个RAW通知有点意思,玩起来会比较有意思.官方文档将RAW通知译为“原始通知”,这里还是沿用官方的翻译. 在开始吹牛之前,先说一说与推送通知相关的要点. 有人说,如果我有22222222个客户端,岂不是都要获取每个手机客户端的通道URL来推送吗?是的.于是有人想到了所谓的“极光推送”,忽悠人的,“极光”显然偷换了概念.我们得明确,在什么情况下才会考虑使用推送. 推送好比服务器与手机客户

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

上一篇文章中,已经完成了用于发送通知的服务器端,接下来我们就用这个服务端来测试一下. 在开始测试之前,我们要做一个接收通知的WP应用. 1.启动VS Express for Windows,新建项目,在项目模板中选择“空白应用程序(Windows Phone)”. 2.既然要接收通知,肯定少不了Toast.磁贴这几样常用的通知的,故我们得先准备一些图片. 在“解决方案资源管理器”中,双击打开清单文件,切换到“可见资产”选项卡,这个“资产”指的不你的银行卡存款有多少,而是你的应用中的一些如图片.音

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

所谓推送通知,用老爷爷都能听懂的话说,就是: 1.我的服务器将通知内容发送到微软的通知服务器,再由通知服务器帮我转发消息. 2.那么,微软的推送服务器是如何知道我的服务器要发消息给哪台手机呢?手机客户端应用程序在创建推送通道时,微软的通知服务器会为手机分配一个URL,我的服务器只要知道这个URL就可以向指定的手机发送消息.所以,手机客户端必须通过网络把获取到的手机URL发给我的服务器,方法很多,如使用Socket.HTTP提交.Web服务.WCF等都可以. 要测试推送通知,可以通过WP 8.1的

【Android应用开发技术:图像处理】Bitmap显示性能优化分析

作者:郭孝星 微博:郭孝星的新浪微博 邮箱:[email protected] 博客:http://blog.csdn.net/allenwells Github:https://github.com/AllenWells [Android应用开发技术:图像处理]章节列表 Bitmap经常会消耗大量内存而导致程序崩溃,常见的异常如下所示:java.lang.OutofMemoryError:bitmap size extends VM budget,因此为了保证程序的稳定性,我们应该小心处理程序

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

或许,系统自带的字体不足以体现应用程序的魅力,对于表现极强的汉字来说,更是如此.这时候,我们就会想,要是能把网上下载的艺术字体塞到应用包中,那岂不美哉?那么,这可以实现吗?答案是Yes的. 接下来,阿拉就给大家分别演示WP 8.1两个开发框架中如何嵌入自定义字体. 为啥是两大框架?我们知道从7x到8.0的开发框架是Silverlight for Windows Phone,为了便于兼容和直接项目升级,在8.1中,微软的开发团队依然保留了这个框架:另外一个框架是从Win RT应用移植的API集,这

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

无论你是用Silverlight还是用RT的API来开发,在使用MediaCapture拍照片或录视频时,要是在模拟器上运行会万事大吉:但是,一旦放到真实手机上运行,肯定有人发现了,细心的朋友肯定发现了——不知道为什么,会经常导致手机重启,或者死机. 啊,顺便给大家说说,死机不可怕,也不用重置,也不用刷机,不会丢失资料的,你只要同时按下“音量减”+“电源”两个键,要同时按住,不要放开,大约等10多秒后,会关机,然后你再放开这两个键,这样手机就软启了,不会丢失数据. 不过,如果你的运营商(如中国联

[WP]使用ApacheCordova开发HTML5-WindowsPhone应用程序

下载代码示例 这篇文章介绍 Apache 科尔多瓦,创建使用 HTML5 和 JavaScript,跨平台移动应用程序的框架,并显示了如何使用它为 Windows Phone 开发应用程序. Windows Phone 和其本机开发平台允许您轻松地创建美丽地铁样式的应用程序. 最近诺基亚的伙伴关系,与 Windows Phone 开始越来越多口袋找到出路. 最近的数据发表的研究公司 Gartner Inc. 预测微软操作系统的一个充满希望的未来 (bit.ly/h5Ic32),具有重大的市场零碎

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

在以往的WP7x/8.0开发中,我们使用选择器可以浏览并打开图片.音频.视频等一些特殊文件,在8.0 SDK中的运行时API(从Win 8 app中移植)尽管提供了Windows.Storage.Pickers命名空间,但里面的Picker是不能用的,到了8.1,随着移植的深入和WP的完善,这些Picker们终于可以派上用场了,比如用于打开文件的FileOpenPicker类,用来保存文件的FileSavePicker类等. 使用Picker的好处在于,文件类型不必被限制为特定的几个,而是可以根

【WP 8.1开发】电子罗盘

罗盘,估计也不用我过多介绍,学过初中物理的都知道,不管是指南针,还是指北针,其本质就是用来辨别方向的. 操作电子罗盘伟感器也不复杂,主要就是两个角度: 1.当前方向与磁北的夹角: 2.当前方向与地北的夹角. 同时,我们也了解到,地理北极与地磁北极并不是重合的,存在地偏角.在读取电子罗盘数据时,可以优先考虑读取与地北极的夹角,如果读不到地北极的夹角,再读取磁北极的夹角数据. CompassReading类(位于Windows.Devices.Sensors命名空间)封装了从电子罗盘所读到的数据.