在之前的博客中我们就有提过OpenGLES的常见应用范围,其中有一个就是图片的处理。为了保证效率,Android手机中许多美颜相机、图片处理应用,都用到了OpenGLES来处理图片。上一篇博客中,我们利用OpenGLES 显示出了一张图片,并保证图片正常显示,不会被拉伸和压缩。在本篇博客中,我们来了解下利用OpenGLES来处理图片的一些简单方法。

相关原理

本篇博客以简单的图片色彩处理、模糊和放大镜效果为例,来学习OpenGL处理图片的过程。

简单色彩处理

使用过PS的朋友应该都知道,PS利用滤镜可以非常方便的更改图片整体色彩。用过诸如美图秀秀之类的傻瓜式图片处理工具也应该记得,它们可以直接选择将图片的风格改为冷色调、暖色调、复古、黑白等等。这些事怎么实现的呢?
在Android应用中,我们设置文字的颜色,控件的背景色,会在资源文件中进行诸如<color name="bg_color">#FF88269F</color>之类的定义。这个#FF88269F就是我们期望的色彩,我们可以把这个色彩分为4部分,每两位组成一部分,分别表示A(透明通道)、R(红色通道)、G(绿色通道)、B(蓝色通道)。每一部分都由两位十六进制的数表示,也就是取值范围都是0-255,根据各个通道的比率不同,显示出来的最终色彩也就不同了。
在其他的编程语言中,也是和这种方式大同小异。在GLSL中,颜色是用包含四个浮点的向量vec4表示,四个浮点分别表示RGBA四个通道,取值范围为0.0-1.0。我们先读取图片每个像素的色彩值,再对读取到的色彩值进行调整,这样就可以完成对图片的色彩处理了。
我们应该都知道,黑白图片上,每个像素点的RGB三个通道值应该是相等的。知道了这个,将彩色图片处理成黑白图片就非常简单了。我们直接出处像素点的RGB三个通道,相加然后除以3作为处理后每个通道的值就可以得到一个黑白图片了。这是均值的方式是常见黑白图片处理的一种方法。类似的还有权值方法(给予RGB三个通道不同的比例)、只取绿色通道等方式。
与之类似的,冷色调的处理就是单一增加蓝色通道的值,暖色调的处理可以增加红绿通道的值。还有其他复古、浮雕等处理也都差不多。

图片模糊处理

图片模糊处理相对上面的色调处理稍微复杂一点,通常图片模糊处理是采集周边多个点,然后利用这些点的色彩和这个点自身的色彩进行计算,得到一个新的色彩值作为目标色彩。模糊处理有很多算法,类似高斯模糊、径向模糊等等。

放大镜效果

放大镜效果相对模糊处理来说,处理过程也会相对简单一些。我们只需要将制定区域的像素点,都以需要放大的区域中心点为中心,向外延伸其到这个中心的距离即可实现放大效果。具体实现,可参考着色器中vChangeType=4时的操作。

图片处理实例

根据图片色彩处理的原理,我们对图片进行色彩上的处理。本实例中包含了图片转换为黑白图片、冷色调处理、暖色调处理三种,其他诸如此类的简单处理可以依照此方法扩展处理。
首先,我们还是先写着色器程序。顶点着色器可以继续使用上篇博客中的顶点着色器,修改片元着色器为:

precision mediump float;uniform sampler2D vTexture;
uniform int vChangeType;
uniform vec3 vChangeColor;
uniform int vIsHalf;
uniform float uXY;      //屏幕宽高比varying vec4 gPosition;varying vec2 aCoordinate;
varying vec4 aPos;void modifyColor(vec4 color){color.r=max(min(color.r,1.0),0.0);color.g=max(min(color.g,1.0),0.0);color.b=max(min(color.b,1.0),0.0);color.a=max(min(color.a,1.0),0.0);
}void main(){vec4 nColor=texture2D(vTexture,aCoordinate);if(aPos.x>0.0||vIsHalf==0){if(vChangeType==1){    //黑白图片float c=nColor.r*vChangeColor.r+nColor.g*vChangeColor.g+nColor.b*vChangeColor.b;gl_FragColor=vec4(c,c,c,nColor.a);}else if(vChangeType==2){    //简单色彩处理,冷暖色调、增加亮度、降低亮度等vec4 deltaColor=nColor+vec4(vChangeColor,0.0);modifyColor(deltaColor);gl_FragColor=deltaColor;}else if(vChangeType==3){    //模糊处理nColor+=texture2D(vTexture,vec2(aCoordinate.x-vChangeColor.r,aCoordinate.y-vChangeColor.r));nColor+=texture2D(vTexture,vec2(aCoordinate.x-vChangeColor.r,aCoordinate.y+vChangeColor.r));nColor+=texture2D(vTexture,vec2(aCoordinate.x+vChangeColor.r,aCoordinate.y-vChangeColor.r));nColor+=texture2D(vTexture,vec2(aCoordinate.x+vChangeColor.r,aCoordinate.y+vChangeColor.r));nColor+=texture2D(vTexture,vec2(aCoordinate.x-vChangeColor.g,aCoordinate.y-vChangeColor.g));nColor+=texture2D(vTexture,vec2(aCoordinate.x-vChangeColor.g,aCoordinate.y+vChangeColor.g));nColor+=texture2D(vTexture,vec2(aCoordinate.x+vChangeColor.g,aCoordinate.y-vChangeColor.g));nColor+=texture2D(vTexture,vec2(aCoordinate.x+vChangeColor.g,aCoordinate.y+vChangeColor.g));nColor+=texture2D(vTexture,vec2(aCoordinate.x-vChangeColor.b,aCoordinate.y-vChangeColor.b));nColor+=texture2D(vTexture,vec2(aCoordinate.x-vChangeColor.b,aCoordinate.y+vChangeColor.b));nColor+=texture2D(vTexture,vec2(aCoordinate.x+vChangeColor.b,aCoordinate.y-vChangeColor.b));nColor+=texture2D(vTexture,vec2(aCoordinate.x+vChangeColor.b,aCoordinate.y+vChangeColor.b));nColor/=13.0;gl_FragColor=nColor;}else if(vChangeType==4){  //放大镜效果float dis=distance(vec2(gPosition.x,gPosition.y/uXY),vec2(vChangeColor.r,vChangeColor.g));if(dis<vChangeColor.b){nColor=texture2D(vTexture,vec2(aCoordinate.x/2.0+0.25,aCoordinate.y/2.0+0.25));}gl_FragColor=nColor;}else{gl_FragColor=nColor;}}else{gl_FragColor=nColor;}
}

为了简便,三个处理使用的是同一个片元着色器,在里面进行了判断。vIsHalf表示是否只处理一半,便于对比原图和处理后的结果。vChangeType为1时,为黑白处理。为2时,作为冷暖色调处理,当然传入其他vChangeColor还可以作为其他的处理。为3时候,作为图片模糊处理。为4时,作为放大镜效果处理。

之后其他的代码和显示贴图代码基本相同,只需要传入vChangeTypevChangeColor依旧vIsHalf的值就可以了。为了方便,可将各种颜色处理封装到枚举类中,如下:

public enum Filter{NONE(0,new float[]{0.0f,0.0f,0.0f}),GRAY(1,new float[]{0.299f,0.587f,0.114f}),COOL(2,new float[]{0.0f,0.0f,0.1f}),WARM(2,new float[]{0.1f,0.1f,0.0f}),BLUR(3,new float[]{0.006f,0.004f,0.002f}),MAGN(4,new float[]{0.0f,0.0f,0.4f});private int vChangeType;private float[] data;Filter(int vChangeType,float[] data){this.vChangeType=vChangeType;this.data=data;}public int getType(){return vChangeType;}public float[] data(){return data;}}

处理结果如下所示:

源码

所有的代码全部在一个项目中,托管在Github上——Android OpenGLES 2.0系列博客的Demo

欢迎转载,转载请保留文章出处。湖广午王的博客[http://blog.csdn.net/junzia/article/details/52902189]

Android OpenGLES2.0(九)——利用OpenGL进行图片处理相关推荐

  1. Android OpenGLES2.0(十七)——球形天空盒VR效果实现

    在3D游戏中通常都会用到天空盒,在3D引擎中也一般会存在天空盒组件,让开发者可以直接使用.那么天空盒是什么?天空盒又是如何实现的呢?本篇博客主要介绍如何在Android中利用OpenGLES绘制一个天 ...

  2. Android解码输出yuv,Android OpenGLES2.0 直接导出YUV420数据

    Android OpenGLES2.0中提供的glReadPixels方法提供的格式只有RGB的几种格式,但是这并不妨碍我们导出YUV格式的数据,因为不管是RGBA还是YUV,都不是glReadPix ...

  3. Android OpenGLES2.0(十四)——Obj格式3D模型加载

    转自:http://blog.csdn.net/junzia/article/details/54300202 在博主<OpenGLES系列>文章中,最开始的几篇讲的就是OpenGL世界中 ...

  4. Android OpenGLES2.0(五)——绘制立方体

    上篇博客中我们提到了OpenGLES中绘制的两种方法,顶点法和索引法.之前我们所使用的都是顶点法,这次绘制立方体使用索引法来绘制立方体. 构建立方体 上篇博客讲到正方形的绘制,立方体是是由六个正方形组 ...

  5. Android OpenGLES2.0(三)——等腰直角三角形和彩色的三角形

    上一篇博客中我们已经绘制出了一个直角三角形,虽然我们相对于坐标,我们设置的直角三角形的两腰是相等的,但是实际上展示出来的却并不是这样,虽然通过计算,我们可以把三角形的两腰计算一下比例,使它们在坐标上不 ...

  6. Android OpenGLES2.0(十六)——3D模型贴图及光照处理(obj+mtl)

    转自:http://blog.csdn.net/junzia/article/details/58272305 在Android OpenGLES2.0(十四)--Obj格式3D模型加载中实现了Obj ...

  7. Android 7.0下拍照和裁剪图片

    Android 7.0下拍照和裁剪图片 最近,公司的APP集中爆发了头像上传中拍照或照片裁剪的bug,让我才意识到及时学习Android新特性是多么重要,一个过去式的APP是无法一直满足日益变化的新需 ...

  8. opengl生成图片php,(转)使用OpenGL显示图像(七)Android OpenGLES2.0——纹理贴图之显示图片...

    转:http://blog.csdn.net/junzia/article/details/52842816 前面几篇博客,我们将了Android中利用OpenGL ES 2.0绘制各种形体,并在上一 ...

  9. Android OpenGLES2.0(一)OpenGLES2.0基础介绍

    文章目录 什么是OpenGL ES? OpenGL ES可以做什么? OpenGL ES版本及Android支持情况 OpenGL ES 2.0的优点 OpenGL ES 2.0中基本概念 顶点着色器 ...

最新文章

  1. 【灵动直播提醒】全国大学生智能车竞赛培训(一)——灵动MM32SPIN27介绍
  2. 百面机器学习——第一章特征工程
  3. 【课题总结】OpenCV 抠图项目实战(12)源程序代码
  4. prev php,PHP prev() 函数 ——jQuery中文网
  5. shell正则表与文本工具sed
  6. 多麦克风做拾音的波束_【技术交流】音控未来——进击的麦克风阵列技术
  7. 百度文库复制文字(一个按钮,关闭JS功能即可,浏览器100%有效)2021年
  8. 练习27——IO流的所有用法(二)
  9. 08. 微信公众号生成带参数二维码
  10. php opcode 启用,Drupal8安装提示PHP OPCODE CACHING未启用的解决方法
  11. 绝对爆笑,虽然我知道可能和别的人雷同,但欢声笑语不雷同不是么?
  12. 心理正常与异常的区分_正常心理与异常心理的判别标准
  13. Vue.js项目实战开发(4)- 必掌握知识点 - #博学谷IT学习技术支持#
  14. swfobject.js 的用法
  15. gateway使用教程
  16. android 蓝牙 自动扫描,android蓝牙扫描(简单
  17. 4.案例 - NIO实现TCP通信
  18. 小程序推送服务通知(前后端代码)
  19. 《Non-contact Eye Gaze Tracking System by Mapping of Corneal Reflections》论文阅读
  20. 依托Airship,ATT走进混合云的世界

热门文章

  1. mac 安装/启动/重启/停止 nginx
  2. 什么是Sql Server游标
  3. 高效自媒体平台必备:苹果CMS资讯采集规则
  4. 通过ls查看文件属性
  5. Anaconda、Python和Pycharm关系
  6. android 联系人 字母索引,Android ListView字母索引(仿微信通訊錄列表)
  7. 代码炼金术9 项目修炼4 判断力
  8. Mshomenbsp;无法访问。您可能没有权限…
  9. 《算法思维——一种问题驱动的思维方式》之第9篇:数据结构之动态栈篇——采用JavaScript编程语言实现
  10. 网络、互联网、因特网的基本概念与组成