Swift 实现图片转字符画的功能
2016-06-21 11:28
387 查看
本文介绍一个IOS APP , 将图片转换成ASCII字符画,使用Swift语言编写。
举个例子,我们使用著名的蕾娜照片作为原图片
![](http://7xjq5l.com1.z0.glb.clouddn.com/lenna.png)
经APP转换后形成的字符画,我们打印出来,效果如下:
![](http://7xjq5l.com1.z0.glb.clouddn.com/lenna_ascii.png?w=510&h=723)
放大她的脸部可以看到图像都是字符串组成的!
![](http://7xjq5l.com1.z0.glb.clouddn.com/lenna_ascii_eyes.png?w=640)
项目地址: https://github.com/ijoshsmith/swift-ascii-art
![](http://7xjq5l.com1.z0.glb.clouddn.com/little_black_box.png?w=300&h=157)
图像中的每个像素都会被转换成一个中间值,如下所示:
![](http://7xjq5l.com1.z0.glb.clouddn.com/pipeline1.png?w=347&h=650)
让我们一步步来分析。
首先,我们将一个像素颜色转换为一个灰度颜色。
灰度颜色的强度(比如:亮度)是介于0和1的一个值,0代表黑色,1代表白色。
接着,把每个颜色的强度值转换为ASCII字符。这对我来说,是最感兴趣的部分,
AsciiPalette类实现了这部分算法,我们等一下分析。
最后,将每行的ASCII字符合并在一起,再将多行字符串合并后就形成了:字符图
![](https://ijoshsmith.files.wordpress.com/2015/04/artist1.png?w=640&h=984)
AsciiArtist 对象依赖Pixel和 AsciiPalette类, 我们等下分析。
每个byte代表一个通道(red, green, blue, and alpha)。
AsciiArtist类通过Pixel类确定其颜色的强度值,把像素强度值转换为一个百分数,
让我们看看是怎么实现的:
![](http://7xjq5l.com1.z0.glb.clouddn.com/pixel.png?w=640&h=747)
上面代码中的 47 到49行,是标准的像素灰度化转换方法,如果你关心这部分原理,可以参考Grayscale
我们根据转换后的强度值作为索引,在AsciiPalette对象的字符数组中找到对应的字符,
字符数组是根据颜色强度值从暗到亮排列的。
下面就是我们方法的实现:
![](http://7xjq5l.com1.z0.glb.clouddn.com/symbol_from_intensity.png?w=487&h=156)
symbol_from_intensity
那么问题是:我们要把哪些ASCII字符放在数组里,按什么样的顺序排列呢?
设计不良的字符数组,会输出不清晰的ASCII字符图:
![](http://7xjq5l.com1.z0.glb.clouddn.com/bat_noise.png?w=440&h=602)
一个良好的字符数组,会生成非常清晰的效果:
![](http://7xjq5l.com1.z0.glb.clouddn.com/bat_signal.png?w=440&h=604)
我的目标是设计一个好的字符数组,使电脑可以绘制出清晰的字符图。
AsciiPalette 类将字符呈现为一个个图像,在白色的背景上绘制黑色的文本。
我们通过计算ASCII字符图像中白色像素的比率,对字符数组进行排序;白色像素越多,字符对应的强度值越大;空格字符(‘ ’)代表最高强度的值,因为它只包含白色像素,所以排在字符数组的最后。
![](http://7xjq5l.com1.z0.glb.clouddn.com/palette.png?w=640&h=860)
AsciiPalette 类初始化需要一个 UIFont 对象作为参数, 因为选择不同的字体,字符的呈现效果不同,这会影响字符周围有多少白色像素。
源码地址: https://github.com/ijoshsmith/swift-ascii-art
本文译自:Creating ASCII art in functional Swift
文/阳春面(简书作者)
原文链接:http://www.jianshu.com/p/19d609c79ee5
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
举个例子,我们使用著名的蕾娜照片作为原图片
![](http://7xjq5l.com1.z0.glb.clouddn.com/lenna.png)
经APP转换后形成的字符画,我们打印出来,效果如下:
![](http://7xjq5l.com1.z0.glb.clouddn.com/lenna_ascii.png?w=510&h=723)
放大她的脸部可以看到图像都是字符串组成的!
![](http://7xjq5l.com1.z0.glb.clouddn.com/lenna_ascii_eyes.png?w=640)
项目地址: https://github.com/ijoshsmith/swift-ascii-art
字符画原理
图像中的每个像素都对应到一个ASCII值,在这里显示为一个字符。![](http://7xjq5l.com1.z0.glb.clouddn.com/little_black_box.png?w=300&h=157)
图像中的每个像素都会被转换成一个中间值,如下所示:
![](http://7xjq5l.com1.z0.glb.clouddn.com/pipeline1.png?w=347&h=650)
让我们一步步来分析。
首先,我们将一个像素颜色转换为一个灰度颜色。
灰度颜色的强度(比如:亮度)是介于0和1的一个值,0代表黑色,1代表白色。
接着,把每个颜色的强度值转换为ASCII字符。这对我来说,是最感兴趣的部分,
AsciiPalette类实现了这部分算法,我们等一下分析。
最后,将每行的ASCII字符合并在一起,再将多行字符串合并后就形成了:字符图
算法实现
AsciiArtist类实现了图像到字符画的转换,参考下图中的 31到 33行.![](https://ijoshsmith.files.wordpress.com/2015/04/artist1.png?w=640&h=984)
AsciiArtist 对象依赖Pixel和 AsciiPalette类, 我们等下分析。
像素转换为灰度颜色
Pixel 类代表图像中的一个像素颜色,一个颜色有4个byte组成,每个byte代表一个通道(red, green, blue, and alpha)。
AsciiArtist类通过Pixel类确定其颜色的强度值,把像素强度值转换为一个百分数,
让我们看看是怎么实现的:
![](http://7xjq5l.com1.z0.glb.clouddn.com/pixel.png?w=640&h=747)
上面代码中的 47 到49行,是标准的像素灰度化转换方法,如果你关心这部分原理,可以参考Grayscale
转换灰度颜色到ASCII字符
AsciiArtist类中的symbolFromIntensity 方法可以转换一个灰度颜色为一个ASCII字符,我们根据转换后的强度值作为索引,在AsciiPalette对象的字符数组中找到对应的字符,
字符数组是根据颜色强度值从暗到亮排列的。
下面就是我们方法的实现:
![](http://7xjq5l.com1.z0.glb.clouddn.com/symbol_from_intensity.png?w=487&h=156)
symbol_from_intensity
那么问题是:我们要把哪些ASCII字符放在数组里,按什么样的顺序排列呢?
设计不良的字符数组,会输出不清晰的ASCII字符图:
![](http://7xjq5l.com1.z0.glb.clouddn.com/bat_noise.png?w=440&h=602)
一个良好的字符数组,会生成非常清晰的效果:
![](http://7xjq5l.com1.z0.glb.clouddn.com/bat_signal.png?w=440&h=604)
我的目标是设计一个好的字符数组,使电脑可以绘制出清晰的字符图。
AsciiPalette 类将字符呈现为一个个图像,在白色的背景上绘制黑色的文本。
我们通过计算ASCII字符图像中白色像素的比率,对字符数组进行排序;白色像素越多,字符对应的强度值越大;空格字符(‘ ’)代表最高强度的值,因为它只包含白色像素,所以排在字符数组的最后。
![](http://7xjq5l.com1.z0.glb.clouddn.com/palette.png?w=640&h=860)
AsciiPalette 类初始化需要一个 UIFont 对象作为参数, 因为选择不同的字体,字符的呈现效果不同,这会影响字符周围有多少白色像素。
源码地址: https://github.com/ijoshsmith/swift-ascii-art
本文译自:Creating ASCII art in functional Swift
文/阳春面(简书作者)
原文链接:http://www.jianshu.com/p/19d609c79ee5
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
相关文章推荐
- Swift 算法实战之路:栈和队列
- Swift-基础-7
- GlusterFS替代OpenStack 的swift模块
- Swift - 告警提示框(UIAlertController)的用法
- Swift - 滑块(UISlider)的用法
- Swift - 进度条(UIProgressView)的用法
- Swift - 图像控件(UIImageView)的用法
- Swift - 分段选择控件(UISegmentedControl)的用法
- Swift - 开关按钮(UISwitch)的用法
- swift Array 数组
- swift2.0 学习笔记Eighteen
- swift学习代码笔记
- swift项目中极光推送
- Swift - 文本输入框(UITextField)的用法
- Swift - 文本标签(UILabel)的用法
- Swift - 文件,文件夹操作大全
- Swift - 按钮(UIButton)的用法
- swift学习笔记3——类、结构体、枚举
- swift第二季高级语法
- swift中关于String类型的successor()