前面我们针对 SVG 的解析和绘制做了介绍,SVG 是图片的一种形式,而另一种很重要的图片是:位图,包括 png、jpeg、bmp 等格式。位图的基本规则是,组成的基本元素是像素点,由宽度 * 高度个像素组成,每个像素存储了一个点的颜色和位置信息,颜色信息可以是 ARGB、RGBA、BGR 或 YUV 等组成。在手绘视频中,位图也是一种很重要的表现形式,因为我们在网上下载的图片,或者自己拍摄的照片,都是位图形式,我们可以用它来做成相册类型的视频等等。下面看一个用户使用来画Pro制作的视频中的截图,用户制作的是一个旅游方面的视频,每个景点的图片都是位图,人物也有一部分位图,这就是位图在手绘视频中的一种表现形式:
下面来详细介绍一下位图在手绘视频中的普通绘制方式:
一般来讲,如果对于位图的处理会简单粗暴一些,就是采用一种默认的方式,而不是图片信息包含的路径数据(因为位图本身没有路径数据),来绘制位图,比如从位图的左上角开始,按照固定的间隔绘制直至位图的右下角完毕。绘制过程效果如下图:
我们看到上面一张 png 位图的绘制过程,从左上角开始,以某个角度的倾斜完成左到右的画笔描绘,而以另一个相近的角度完成从右到左的画笔绘制,最终到完成整个位图的绘制。而这整个过程的处理流程和示意图如下:
其中,初始化图片资源和动画路径数据,分别用到 CanvasBitmap 和 CanvasGeometry;而转换绘制动画路径的点集使用 CanvasGeometry.ComputePointOnPath(float distance),最终得到的 distance 就是绘制的总长度;而绘制过程使用的是 CompositeEffect。
以上是所谓简单粗暴的处理方式,作为一个 bige 高的专业工具,怎么可能没有专业的处理方式呢,往下看:
在应用内,我们提供了两种方式来获取位图的路径数据,一种是利用 OpenCV 获取图片的物体边缘数据,另一种是让用户自己定义想以怎样的路径描绘位图。
第一种很容易理解,首先膜拜一下 OpenCV,计算机视觉方面的神器,我们这里使用的就是 OpenCV 的边缘检测方法,它和图像平滑算法相反,是一种“高通滤波器”,去检测图像中像素跨度很大的点组成的边缘,例如物体景观的深度不连续,多面体表面方向的不连续,光照和阴影的临界,物体表面材质不一致的临界等,使用的方法有 Sobel,Laplacian 和 Canny,我们使用的是 Canny,效果如下图:
位图按照检测到的边缘路径一点点描绘出来,只有路径划过的地方才显示位图,这样就有了路径描绘的视觉感受。其实这也是画师在素材制作中一种很常见的方式,在 PS 中处理静态图片的特效,处理完成后保存导入到 AI 中,在静态图片上面描画透明路径,描绘完成后保存成 SVG 文件。这就是一种比较特殊的 SVG,包含了一张位图作为底图,而透明路径的作用,是在路径描绘时,显示路径对应位置的位图像素。
另外一种方式,更多的由用户自己来操作实现,相当于把我们的应用当作 AI,用户自己准备的静态图片,放到应用中进行上面所说的路径描绘,然后直接导入到应用内作为 SVG 使用。应用的界面和操作如下:
上面图1是用户操作界面,用户可以指定画笔的粗细来描绘路径,描绘完成后,会以图2到图3的过程来描述位图。如图1中我们指定的路径是先画头像的边框,再用粗的画笔描绘头像的填充,就如图2和图3的过程一样。
上述的两种处理方式,一个是由系统来检测位图的边缘,另一个是由用户来指定边缘,我们计划把两种方式结合在一起,先由系统检测,再由用户补充和纠正,这样可以减少用户操作的难度,因为有些位图的边缘会很复杂。另外系统检测的一个缺点就是,边缘路径是完全无序,没有分组的,就是说路径不会按照物体的区别分组绘制,也不会按照某个固定顺序绘制,这都需要我们后续再去处理,根据边缘路径的相连属性去分组,在根据方向上的某个顺序去处理排序,当然这还是一种简单粗暴的处理方法。更深一层的处理,应该是检测边缘时,识别物体分类,也就是物体是什么?然后根据这些信息分组和按照分类去排序。这些都是我们后面要做的事情。
位图的处理方式就介绍到这里了,如果大家有好的处理方法,或者有好的想法,欢迎联系我,感谢!