博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【WP 8.1开发】How to 图像处理
阅读量:5221 次
发布时间:2019-06-14

本文共 5086 字,大约阅读时间需要 16 分钟。

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

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

开发工具

115网盘礼包码: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进行计算。代码如下:

///         /// 灰度处理        ///         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

///         /// 反色        ///         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
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.

示例下载:

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

88。

 

转载于:https://www.cnblogs.com/tcjiaan/p/4231886.html

你可能感兴趣的文章
监控工具之---Prometheus 安装详解(三)
查看>>
不错的MVC文章
查看>>
网络管理相关函数
查看>>
IOS Google语音识别更新啦!!!
查看>>
20190422 T-SQL 触发器
查看>>
[置顶] Linux终端中使用上一命令减少键盘输入
查看>>
poj1422_有向图最小路径覆盖数
查看>>
BootScrap
查看>>
[大牛翻译系列]Hadoop(16)MapReduce 性能调优:优化数据序列化
查看>>
WEB_点击一百万次
查看>>
CodeForces - 878A Short Program(位运算)
查看>>
路冉的JavaScript学习笔记-2015年1月23日
查看>>
Mysql出现(10061)错误提示的暴力解决办法
查看>>
2018-2019-2 网络对抗技术 20165202 Exp3 免杀原理与实践
查看>>
NPM慢怎么办 - nrm切换资源镜像
查看>>
CoreData 从入门到精通(四)并发操作
查看>>
Swift - UIView的常用属性和常用方法总结
查看>>
Swift - 异步加载各网站的favicon图标,并在单元格中显示
查看>>
Java编程思想总结笔记Chapter 5
查看>>
[LeetCode]662. Maximum Width of Binary Tree判断树的宽度
查看>>