神笔马良——基于 OpenGL 的涂鸦框架

取这个名字有投机取巧的嫌疑,希望能对得起先贤 >_<

这是什么?

MaLiang 是 iOS 平台一个基于 OpenGL ES3 的涂鸦绘图库,使用纯 Swift 实现,支持自定义纹理、压力感应、自动笔触等特性,并且提供了一定的自定义扩展的空间。

这篇文章可以看作是对 Github 上 README 说明的详细扩展和补充说明。

使用

我的理念是尽量制造简单、优雅的东西,虽然有时候要做到这一点其实很难,但是尽量往这方面靠吧。MaLiang 的集成和使用都很简单,我把大量对使用者来说没有什么用也没有必要了解的内部逻辑都隐藏了。当然了,如果你的好奇心很重,可以自己去看源代码。这篇文章也会介绍一些内部实现的思路。

集成

MaLiang 已经推送到了 Cocopods 的官方 repo,所以,你只需要在 Podfile 增加一条 Pod 指令然后 install 就可以在项目中使用了:

pod 'MaLiang'复制代码

然后在需要使用的地方引入 Mudule。当然,首先需要编译一下,否在会报找不到 Moudle 的错误

import MaLiang复制代码

几个主要的类

1. Canvas

画布是 MaLiang 最基础的组件,所有的涂鸦都发生在 Canvas 上。Canvas 本质上是一个 UIView,所以你可以使用任何你原来创建 UIView 的方法来创建一个画布,并将它添加到你的界面上。

  • 如果你偏好代码流,那么直接调用 UIView 的通用构造函数 init(frame:) 就可以了。
  • 如果你觉得 IB 流才是正道,只要在 xib 或者 storyboard 中拖一个 UIView 到界面上,然后将类名改成 Canvas 后回车就可以了,Xcode 应该会自动将 Module 设置成 MaLiang。

给 Canvas 设置正确的布局约束,然后你就可以开始涂鸦了,比如写一个像下面这样的东东 :)

嗯,想画成这样,确实还缺少一些东西 :)

Canvas 继承自 MLView(ML是 MaLiang 的缩写,不是那个机器学习的东东),MLView 做了几乎所有与 OpenGL 打交道的事情,虽然它被定义成一个 open 的类,但实际使用中基本是用不到的。不过了解一些原理也无伤大雅么~

OpenGL 涂鸦的核心是纹理(Texture),本质上就是沿着手指轨迹,不断地将纹理叠加到画布上的过程。所以能画出什么样的笔迹,完全取决于使用的纹理,以及它的大小、颜色、尺寸等参数。

MLView 初始化之后会使用自带的图片创建一个默认的纹理,这个纹理就是一个简单的不透明的圆点,所以只能画最简单的线条。如果想要画出上图那样的效果,就需要使用相对复杂一点的纹理了。MaLiang 的示例项目里面提供了好几个设定好的纹理,用他们可以模拟出铅笔、水笔以及毛笔的特效,上面的文字就是使用毛笔特效写出来的。

快照

Canvas 提供了一个简单的快照功能:

open func snapshot() -> UIImage?复制代码

调用该方法会对画布生成一个当前内容的快照并以 Image 的形式返回,快照的实现逻辑很简单,你也可以自己实现更加复杂的快照逻辑。

2. Brush

直接使用纹理还是比较繁琐的,另外与纹理相关的还有颜色、线条的粗细以及其他一些参数,所以这里提供了一个 Brush 类来处理所有的这些数据。

Brush 的属性在改变后会立刻影响接下来的绘制效果。

  • opacity 透明度

上面提到,涂鸦的本质是把纹理叠加到画笔的过程,所以想要做出深浅不一的笔迹,纹理就需要具有透明度,可以通过opacity 属性来调节。

  • pointSize 笔迹粗细

pointSize 直接影响笔迹的粗细,它是以 iOS 尺寸的标准单位 点(point) 来衡量的,所以这是一个自适应屏幕像素密度的属性。你不需要根据设备类型来计算实际像素,直接指定眼睛可见的大小就可以了。

  • pointStep 点距

同上,由于笔迹是通过叠加纹理实现的,因此除了透明度外,两个纹理之间的距离也会影响到笔迹的深浅。另外如果把点距设定到大于笔迹的尺寸,甚至可以画出类似虚线的效果。点距的单位也是 点(point)

  • forceSensitive 压力敏感度

之所以说 pointSize 是影响笔迹的粗细,而不是直接确定,是因为有压力感应的存在。笔迹的实际尺寸会随着压力的大小在 pointSize 指定的尺寸上下浮动,压力越大,笔迹越粗。forceSensitive 影响笔迹对压力浮动的剧烈程度,建议设置为 0 - 1 之间的某个值。如果设置过大,笔迹随压力的便会会太过剧烈而失真;如果将 forceSensitive 的值设置为 0,则对该画笔关闭压力感应效果,笔迹粗细不会随着压力而变化。

MaLiang 默认使用 iOS 设备的压力感应特性,另外在一些不支持压力感应的设备上使用模拟的压力感应。模拟压感依赖手势移动的速度来判断压力的大小,速度越快压力越小。

  • color 颜色

影响笔迹的颜色,实际画出的颜色会计算进 opacity 的值,不过由于纹理之间会叠加,所以相互效果可以基本抵消。你一般不需要为颜色额外指定透明度的值。

  • texture 纹理

texture 是一个非公开属性,实际使用时只需要使用纹理图的 Image 初始化 Brush 对象就可以了,不需要关心 texture 的具体实现。

实际绘制时的颜色是设定的 color 与纹理的颜色混合之后的结果,所以需要保证纹理图是白色的,才能确保绘制正确的颜色。这个问题可能会在未来改善。

texture 实际上是一个 MLTexture 类型的对象,MLTexture 内部分装了纹理相关的 OpenGL 实现,包括创建纹理、切换画笔时的纹理绑定等。

3. Document

Document 不是实现涂鸦的必备组件,它是为了提供一些更加深入的功能而设计的。Document 维护着持有它的画布的所有笔迹数据,依赖这些数据,可以实现撤销和重做功能。这两个功能 MaLiang 已经默认实现。

通过 Document 持有的数据,你还可以轻松实现保存涂鸦数据到文件的逻辑。反过来也可以将保存的数据重新还原成画布图像,这样可以实现跨设备的数据同步功能。

Document 功能默认是没有启用的,需要手动通过代码开启:

canvas.setupDocument()复制代码

Document 在运行过程中需要使用一部分硬盘空间来存放临时数据,所以如果设备存储空间不足时,上面的操作会抛出一个异常,为了保证程序的健壮性,建议使用 do-catch 模式来捕获可能的异常情况:

do { try canvas.setupDocument()} catch { // do somthing when error occurs}复制代码

计划实现的一些特性

计划中 MaLiang 还存在一些尚未实现的特性,这些特性会在未来逐渐添加进来,当然,你也帮助我实现,然后给我提交 PR :)

  • [x] 撤销 & 重做,目前已经实现
  • [x] 导出图片,已实现
  • [ ] 绘制文本到画布中的指定位置
  • [ ] 绘制指定的图片到画布中的指定位置
  • [ ] 纹理旋转,旋转纹理可以实现一些更加特殊的笔迹效果

由来

MaLiang 起源于多年前的一个涂鸦项目,当时还是基于 Objective-C 和 OpenGL ES1 实现的,OpenGL ES1 对于抗锯齿的支持不是很好,所以涂鸦的效果不怎么敢恭维。并且当时由于太年轻,整个框架的设计和结构都比较凌乱。虽然最后顺利上架了一段时间,不过由于各种各样的原因,整个项目随当时的公司一起无疾而终了。

去年开始重拾这个项目,打算基于 Swift 和 OpenGL ES3 完全重写,同时将当时处理得不是很好的地方加以改进,另外扩展了一些自己近期想到的东西,最终诞生了这个库。

Why Swift?

使用 Swift 直接和 OpenGL 打交道确实不是一件容易的事情,有人奉劝我使用 OC 或者 C 作为中间层来调用 OpenGL,再用 Swift 封装上层逻辑,确实这样可以以最低的成本实现需要的效果。

不过作为一个业余项目,成本并不是我第一考虑的要素,而且这个库虽然是基于 OpenGL 的,但是真正跟 OpenGL 打交道的,其实也就那几百行代码。为了追求这一点点成本和便利性,牺牲整个项目结构的统一和整洁,在我这是无法接受的。

另外,引入 OC 代码意味着同时引入了 OC 的动态运行时环境,这对 Swift 的执行效率会有一定的影响。虽然作为一个 iOS 的项目,现在必然无法摆脱 OC 的动态运行时环境,我的这点偏执似乎也没有什么意义,不过谁知道以后会怎么样呢 :)

应用

说了半天,这个库有什么用?说实话我也不知道,或许可以用来做签名?不过签名其实用 CoreGraphics 就足够了。或许可以用它来做一个画画的 App 来逗小孩玩,可能我真会这么干。。。

说到底,这主要是对当初懵懂时期经历的一个纪念吧。感兴趣的都可以拿去玩 :)

接下来可能会打算基于这个库开发一款涂鸦的 App。当然了,多年前的那个项目是不会复活了,新的这个 App 会是一个融合了很多我自己想法的全新项目。当然了希望不要半途而废 - -!

opengl 图片处理 卷纸弯曲效果_神笔马良——基于 OpenGL 的涂鸦框架相关推荐

  1. 神笔马良——基于 OpenGL 的涂鸦框架

    取这个名字有投机取巧的嫌疑,希望能对得起先贤 >_< 这是什么? MaLiang 是 iOS 平台一个基于 OpenGL ES3 的涂鸦绘图库,使用纯 Swift 实现,支持自定义纹理.压 ...

  2. bootstrap 按钮样式单选效果_【20201117】Bootstrap前端框架学习笔记

    1. 介绍 1.1 介绍 Bootstrap是一个免费的web前端框架,它将HTML.CSS.Javascript结合到一起,制定了一系列的前端开发规则,使设计网页就像搭积木一样简单. 今天我们就跟着 ...

  3. [OpenGL] 期末大作业开源 全套项目+PPT+报告 基于OpenGL 3.3 CORE 环境集成可以直接运行

    本学期的OpenGL大作业做了一个3D二维码生成器: 可以切换相机视角&更多功能等你添加. 可以动态更新纹理: 在数据的准备阶段,需要提取二维码关键点的信息,写了一个python脚本用来生成对 ...

  4. java opengl 图片文字_如何通过opengl显示相机预览

    有两种方法可以使用opengl来显示这个像素数据 在JAVA中使用Opengl 在c或c中使用opengl(JNI) 实际上,无论哪种方式,如果你知道什么是opengl管道就会很容易 我总是因为可重用 ...

  5. html多图轮播淡入淡出js,原生JS实现图片轮播与淡入效果的简单实例

    最近对css的兴趣提不起来,因为以前对图片轮播一直耿耿于怀苦于学艺不精,所以,花了点时间熟悉了一下js.然后一条道走到黑,用jquery和js写了一下轮播和图片淡入的效果.以后学习的路很长,希望自己在 ...

  6. 【每日一练】19—CSS 实现撕纸的效果

    写在前面 今天我们来练习一个CSS实现的撕纸效果,这个效果,也会在一些设计网站上经常看到,但是这个用PS可以直接做成一张图片,但是,今天我们用CSS通过两张图片就实现了,这样做的好处,就是当我们替换图 ...

  7. openglshader实现虚拟场景_基于OpenGL的雨雪场景仿真

    基于 OpenGL 的雨雪场景仿真 张沛露 [期刊名称] <活力> [年 ( 卷 ), 期] 2019(000)020 [总页数] 1 [关键词] [ 关键词 ] 雨雪仿真: OpenGL ...

  8. Ps教程:Photoshop快速把人物图片转为手绘漫画效果

    本篇转载于https://user.qzone.qq.com/907218922/blog/1556084094用于记录学习. Photoshop快速把人物图片转为手绘漫画效果 最终效果 1.打开我们 ...

  9. 市场调研报告-全球与中国自动卷纸分配器市场现状及未来发展趋势

    报告摘要 2019年,全球自动卷纸分配器市场规模达到了xx亿元,预计2026年将达到xx亿元,年复合增长率(CAGR)为xx%. 本报告研究全球与中国市场自动卷纸分配器的产能.产量.销量.销售额.价格 ...

  10. 2021-2027全球与中国电子卷纸分配器市场现状及未来发展趋势

    本报告研究全球与中国市场电子卷纸分配器的产能.产量.销量.销售额.价格及未来趋势.重点分析全球与中国市场的主要厂商产品特点.产品规格.价格.销量.销售收入及全球和中国市场主要生产商的市场份额.历史数据 ...

最新文章

  1. netty集成ssl完整参考指南(含完整源码)
  2. C/C++中“#”和“##”的作用和用法
  3. 自学python需要多长时间-自学Python需要多长时间?
  4. 中值滤波讲解-Matlab
  5. Oracle 10g数据库基础之基本查询语句-中-函数
  6. FileOutputStream为false时候注意的问题
  7. 全球免费数字图书馆TOP30
  8. matlab期货,Matlab在股指期货中的应用
  9. 自动驾驶领域中常见英文缩写、相关含义以及常用专业英文
  10. 迅雷、旋风、快车的下载地址加密算法解析
  11. Python办公自动化之Excel报表自动化,看这一篇就够了!
  12. 如何评价红米 Note 11T系列手机?网友:没有不足
  13. 老鹰-第一次Python笔记
  14. 比较两条曲线的相似程度
  15. 《软件测试常见面试题十二》
  16. java实现PDF 转WORD
  17. 在这个产品同质化比较严重的时代,这个局怎么破?
  18. webpack开发配置API代理解决跨域问题-devServer
  19. 矩阵的基本运算(相乘、相加、求逆、转置)
  20. 使用字节流和字符流对文件进行操作

热门文章

  1. Install R language on Linux RHEL5 or RHEL6
  2. NClay框架AOP功能简介
  3. 软件开发需求整理概要
  4. 时间格式转变 android,Android开发日期时间格式的转化
  5. 浙大计算机基础知识试题及答案,14年浙大远程教育计算机基础4.电子表格Excel 2010知识题(高起专)作业题4答案...
  6. python for 加速_适合练习的10个Python项目,每个项目都不到500行代码
  7. linux sleeping进程多_你知道Linux进程的睡眠和唤醒操作?
  8. AOP面向切面编程(1.6w字长文讲清AOP)
  9. mysql中的concat和group_concat的用法
  10. scrapy -selector