首页 > 其他分享 >在 iOS 上用 Shader 实现 图片 转 字符画 效果~~

在 iOS 上用 Shader 实现 图片 转 字符画 效果~~

时间:2022-12-11 17:31:35浏览次数:73  
标签:字符 highp iOS Shader 纹理 width 灰度 上用 像素点

这两天公众号发布了篇如何将 图片 转换 字符画 效果的文章,不过具体的实现是在 CPU 上的。

那天在朋友圈问了一下如何通过 OpenGL Shader 实现同样效果,没想到引来了大神的关注。

于是就有了如下这篇文章,转载自大佬的实现,文章末尾有源码地址。

对于如何实现将 图片 转换成 字符画 效果,如何你也有好的见解,欢迎投稿,让大家一起学习一下。

效果

实际效果如下:

 

在 iOS 上用 Shader 实现 图片 转 字符画 效果~~_灰度图

  


在 iOS 上用 Shader 实现 图片 转 字符画 效果~~_灰度值_02

 

实现原理

1.1 RGB 转灰度值

首先,我们知道在 OpenGL 中颜色有4个通道RGBA,对于一般图片 ​​A = 1.0​​。那还有3个通道需要处理 RGB。

而我们的字符画使用 1 个字符表示 1 块颜色,即我们需要将 RGB 三个通道进行某种处理(3个值),让它们变为1个值,我们才能对应某 1 个字符。

上面所说的某种处理就是:RGB 值转换为灰度值

 

在 iOS 上用 Shader 实现 图片 转 字符画 效果~~_像素点_03

 

这个部分我们可以通过 shader 进行转换,shader 来自 GPUImageGrayscaleFilter:

precision highp float;
varying vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);
void main()
{
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
float luminance = dot(textureColor.rgb, W);
gl_FragColor = vec4(vec3(luminance), textureColor.a);
}

通过上面的处理,我们就把 RGB 值转换为了灰度值,或者 shader 中的 luminance(亮度值)。

此时,RGB值均等于luminance。(后面直接使用RGB中任何一个值即可)

1.2 灰度值转字符

现在的灰度值范围为 ​​[0,1.0]​​,我们将其量化为15个等级。

等级细分可根据需求自己确定。

由低到高为 ​​[0, 1/15, 2/15,...,1.0]​​:

 

在 iOS 上用 Shader 实现 图片 转 字符画 效果~~_灰度值_04

 

图中文字可自行选择,保证其在图中黑白占比接近对应的等级即可。

1.3 灰度图尺寸转换

如果我们使用一个像素表示一个字符,肯定是看不出字符的形状的,所以一般采用多个像素点表示一个字符的形式来进行显示。

所以未转换成字符的时候,用多个点表示一个灰度,就会得到下面这张马赛克风格的图。

 

在 iOS 上用 Shader 实现 图片 转 字符画 效果~~_灰度图_05

 

示例中,我采用了 ​​10*10​​​ 的像素点来表示一个灰度值。​​10*10​​​ 比较难画,下面我用 ​​5*5​​ 的像素点来解释。

 

在 iOS 上用 Shader 实现 图片 转 字符画 效果~~_灰度图_06

 

如果用 ​​5*5​​ 的像素点来表示1个灰度值,我们需要用25个点的灰度值算一个平均,然后再用这个灰度值去填充25个像素格子。

那如果我把图片的长和宽都缩小5倍,然后用灰度值来绘制,那么 GPU 会帮我们完成计算,而且现在我只需要1个格子。

 

在 iOS 上用 Shader 实现 图片 转 字符画 效果~~_灰度图_07

 

我们再来一个具体的例子,假设我有一张 ​​1000*1000​​​ 的图,通过灰度shader和在 0.1 倍的frame buffer上进行绘制,就可以得到一个 ​​100*100​​ 的灰度图查询的纹理。

即,对于原始图中坐标(x,y),x∈​​[0,9]​​​,y∈​​[0,9]​​ 的这些像素点,只需要使用灰度图查询纹理(0,0)这一个像素点的灰度值即可。

1.4 灰度值映射字符纹理

varying highp vec2 textureCoordinate; // 纹理坐标
varying highp vec2 textureCoordinate2; // 纹理坐标(未用到)

uniform sampler2D inputImageTexture; //字符纹理
uniform sampler2D inputImageTexture2; // 灰度值参考纹理

uniform highp vec2 textureSize; // 原图尺寸

void main()
{
// 像素点坐标
highp vec2 coordinate = textureCoordinate * textureSize;

// demo这里写死,可以根据实际情况调整
highp float width = 10.0;
// 计算width*width的区域的中点
highp vec2 midCoor = min((floor(coordinate / width) * width + width * 0.5) / textureSize, 1.0);
// 得到中点的灰度值
lowp vec4 color = texture2D(inputImageTexture2, midCoor);
// 一个字符的归一化纹理坐标
coordinate = mod(coordinate, width) / width;
// 为了节约性能,15个字符我们放在一个纹理上,需要根据灰度值进行x偏移
coordinate.x = (floor(color.r * 14.0) + coordinate.x) / 15.0;

gl_FragColor = texture2D(inputImageTexture, coordinate);
}
  1. 我们根据纹理坐标和纹理的尺寸算出对应的像素点坐标。
  2. 计算 width*width 的区域的中点,并得到中心点的灰度值。

由于小尺寸的灰度纹理我们是分开得到的,不能保证一定满足我们上面提到的理想效果,所以采用了中心点的灰度值。

  1. 我们用width*width的像素点表示一个字符,计算出对应字符的归一化纹理坐标。
  2. 为了节约性能,由于15个字符纹理我们横向合并在一个纹理中,所以要根据灰度值进行偏移,灰度值选择对应的字符纹理。

Demo 地址

对于如何在 视频 中实现 字符画 效果,就变得很简单了,直接复用源码里面的 filter 就好了,相信关注我公众号的你,一定知道是怎么举一反三了。

源码地址:

作者:收納箱

在 iOS 上用 Shader 实现 图片 转 字符画 效果~~_灰度图_08



标签:字符,highp,iOS,Shader,纹理,width,灰度,上用,像素点
From: https://blog.51cto.com/u_12127193/5928481

相关文章

  • iOS上架辅助软件Appuploader
    iosapp上架流程上架基本需求资料1、苹果开发者账号(如还没账号先申请-苹果开发者账号申请教程)2、开发好的APP通过本篇教程,可以学习到ios证书申请和打包ipa测试上架的完整流程......
  • Linux监控命令之iostat
    一、使用说明iostat是对系统的磁盘I/O操作进行监控,它的输出主要显示磁盘读写操作的统计信息,同时给出CPU的使用情况。同vmstat一样,iostat不能对某个进程进行深入分析,......
  • 开发一个最简单的iOS App
    开发一个最简单的iOSApp大家好,我是孜孜不倦学习的Zhangbeihai。上月底我组织了【组队学习】TensorFlow入门课程(中文),截至目前有300多同学加入。主要就是TensorFlowLi......
  • app提交上架最新流程 ios​
    OverridetheentrypointofanimageIntroducedinGitLabandGitLabRunner9.4.Readmoreaboutthe extendedconfigurationoptions.Beforeexplainingtheav......
  • iOS现有APP上架流程​
    OverridetheentrypointofanimageIntroducedinGitLabandGitLabRunner9.4.Readmoreaboutthe extendedconfigurationoptions.Beforeexplainingtheav......
  • iOS面试题及答案大总结
    1.写一个NSString类的实现+(id)initWithCString:(c*****tchar*)nullTerminatedCStringencoding:(NSStringEncoding)encoding;+(id)stringWithCString:(c*****tch......
  • iOS开源资源收集
    2.json库json-frameworkJSONKit,根据他自己提供的数据它解析的时候比json-framework快4倍,比二进制的.plist 还快25%。​​https://github.com/johnezang/JSONKit​​它......
  • iOS为imageView添加图片实现动画
    iOS为imageView添加图片实现动画代码如下://创建imageView self.imageView=[[UIImageViewalloc]initWithFrame:CGRectMake(0,40,320,260)];  //把图片添加到动态数组......
  • 关闭ios虚拟键盘的几种方法
    在iOS应用开发中,有三类视图对象会打开虚拟键盘,进行输入操作,但如何关闭虚拟键盘,却没有提供自动化的方法。这个需要我们自己去实现。这三类视图对象分别是UITextField,UIText......
  • vite+ts+vue3+router4+Pinia+ElmPlus+axios+mock项目基本配置
    1.vite+TS+Vue3npmcreateviteProjectname:...yourProjectNameSelectaframework:>>VueSelectavariant:>>Typescrit2.修改vite基本配置配置Vite{#configu......