skia draw
来源:互联网 发布:阿里云招聘官网 编辑:程序博客网 时间:2024/05/16 12:40
最近终于有时间去看skia draw的一些过程,参考skia/gm和skia/samplecode里面的示例非常粗略的总结了一下skia的绘制过程,只能说建立一个概览吧。希望有熟悉skia的大神在不对之处可以帮忙指点。
skia的每次绘制都是由canvas.drawXX方法发起,经过path generation、rasterizer、shading和transfer四个步骤完成一张图的绘制。
Path generation
enum Style { kFill_Style, //!< fill the geometry填充 kStroke_Style, //!< stroke the geometry绘制轮廓 kStrokeAndFill_Style, //!< fill and stroke the geometry };
Rasterizer
生成path之后的工作就是要去rasterizer。skia中的rasterizer主要是确定像素要画在哪,这通过使用一个mask图像来完成。mask图像实际上是一个只有alpha通道的灰度图。mask图像可以决定每个像素是全透明、不透明还是部分透明。
可以使用两个方法生成mask:
(1)no rasterizer
使用paint style property和path property进行path扫描转换,产生一个初始的mask。在path内部的像素是不透明的,path外部的像素保持透明,在path边界上的像素部分透明(如果设置anti-aliasing抗锯齿)。
如果设置了maskFilter,初始的mask会根据它进行变换,比如blur、emboss、table等效果。设置步骤为:首先使用SkPaint方法setMaskFilter()为paint分配一个SkMaskFilter;然后具体的mask过滤由SkMaskFilter子类实现。
对于blur效果,可以参考sampleBlur.cpp。
emboss效果,可以参考sampleEmboss.cpp。
(2)rasterizer
由SkRasterizer创建一个mask。
首先使用SkPaint的方法setRasterizer()为paint设置一个SkRasterizer;然后SkRasterizer的rasterize()方法会创建一个mask bitmap,之后把path绘制到这个mask中。
Shading
rasterizer之后就需要进行shading。shading的主要工作是确定像素的颜色,即着色。skia主要支持四种shader:线性梯度shader、环形梯度shader、扫略梯度shader以及混合shader。混合shader用来处理使用两种相同或者不同的shader在xfermode下的混合着色。这部分可以参考sampleShader.cpp例子。
着色过程有两个阶段:第一个阶段是为SkPaint分配一个SkShader,同样也是使用SkPaint的setShader方法。SkShader会生成一个初始的源图像。
在创建shader时,需要指定平铺模式(TileMode),有三种:kClamp_TileMode、kRepeat_TileMode和kMirror_TileMode,分别对应普通平铺、重复平铺和镜像平铺。镜像平铺很好理解,对于普通平铺,如果shader超出着色边界,则会使用边界的颜色延伸到bitmap边界;对于重复平铺,如果shader超出着色边界,则会在边界处重复之前的着色。
如果在这个阶段没有设置SkShader,则需要给paint设置一个color,此时会产生一张单色图像。
第二个阶段:如果为Skpaint设置了colorFilter,则colorFilter会为初始源图像的颜色进行变换。maskFilter与colorFilter不同:maskFilter是对一个paint的alpha通道的转换;而colorFilter是针对RGB通道的转换。所有由colorFilter所派生的类在执行它们的转换时都会忽略alpha通道。
(1)colorFilter可以通过改变colorMatrix进行色彩变换(C1=pin(C*Cm+Ca))。
a ,b ,c, d, e,
f ,g ,h ,i , j,
k ,l, m, n, o,
p ,q ,r ,s ,t
(2)colorFilter也可以通过处理各种XforMode(图像混合模式)来针对dst/src图像进行色彩处理。
这部分的例子可以参考sampleColorFilters.cpp。
Transfer
<pre name="code" class="cpp"><pre name="code" class="cpp"><span style="font-family:Microsoft YaHei;">/* Sa 代表source alpha ,即源 alpha 值 ,Da 代表 Destination alpha ,即 目标alpha值 ,Sc 代表 source color ,即源色值 ,Dc 代表 Destination color ,即目标色值,并且这所有的计算都以像素为单位.[a, c]代表在某一种混合模式下,对每一个像素的alpha 和 color 通过对应算法进行运算,所得出的像素值*/enum Mode { kClear_Mode, //!< [0, 0]清除模式[0,0],即最终所有点的像素的alpha 和color 都为 0,所以画出来的效果只有白色背景 kSrc_Mode, //!< [Sa, Sc]只保留源图像的 alpha 和 color ,所以绘制出来只有源图 kDst_Mode, //!< [Da, Dc]同上类比,只保留目标图像的 alpha 和 color,所以绘制出来的只有目标图 kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Sc + (1 - Sa)*Dc]在目标图片顶部绘制源图像,从命名上也可以看出来就是把源//图像绘制在上方 kDstOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Dc + (1 - Da)*Sc]将目标图像绘制在上方 kSrcIn_Mode, //!< [Sa * Da, Sc * Da]在两者相交的地方绘制源图像,并且绘制的效果会受到目标图像对应地方透明度的影响 kDstIn_Mode, //!< [Sa * Da, Sa * Dc]在两者相交的地方绘制目标图像,并且绘制的效果会受到源图像对应地方透明度的影响 kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]在不相交的地方绘制源图像,相交处根据目标alpha进行过滤,目标色完全//不透明时则完全过滤,完全透明则不过滤 kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]类似上面 kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]源图像和目标图像相交处绘制源图像,不相交的地方绘制目标图像,并且相//交处的效果会受到源图像和目标图像alpha的影响 kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]类似上面 kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]在不相交的地方按原样绘制源图像和目标图像,//相交的地方受到对应alpha和色值影响,按上面公式进行计算,如果都完全不透明则相交处完全不绘制 kPlus_Mode, //!< [Sa + Da, Sc + Dc] kModulate_Mode, // multiplies all components (= alpha and color) // Following blend modes are defined in the CSS Compositing standard: // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending kScreen_Mode, //滤色,滤色模式与我们所用的显示屏原理相同,所以也有版本把它翻译成“屏幕”;简单的说就是保留两个图层中较 //白的部分,较暗的部分被遮盖;当一层使用了滤色(屏幕)模式时,图层中纯黑的部分变成完全透明,纯白部分完全//不透明,其他的颜色根据颜色级别产生半透明的效果 kLastCoeffMode = kScreen_Mode, kOverlay_Mode, //像素是进行 Multiply (正片叠底)混合还是 Screen (屏幕)混合,取决于底层颜色,但底层颜色的高光与阴影部//分的亮度细节会被保留 kDarken_Mode, //该模式处理过后,会感觉效果变暗,即进行对应像素的比较,取较暗值,如果色值相同则进行混合;从算法上看,//alpha值变大,色值上如果都不透明则取较暗值,非完全不透明情况下使用上面算法进行计算,受到源图和目标图对应//色值和alpha值影响 kLighten_Mode, //DARKEN 的目的是变暗,LIGHTEN 的目的则是变亮,如果在均完全不透明的情况下 ,色值取源色值和目标色值中的较大值,//否则按上面算法进行计算 kColorDodge_Mode, kColorBurn_Mode, kHardLight_Mode, kSoftLight_Mode, kDifference_Mode, kExclusion_Mode, kMultiply_Mode, //正片叠底,即查看每个通道中的颜色信息,并将基色与混合色复合。结果色总是较暗的颜色。任何颜色与黑色复合产生黑色。//任何颜色与白色复合保持不变。当用黑色或白色以外的颜色绘画时,绘画工具绘制的连续描边产生逐渐变暗的颜色 kLastSeparableMode = kMultiply_Mode, kHue_Mode, kSaturation_Mode, kColor_Mode, kLuminosity_Mode, kLastMode = kLuminosity_Mode };</span>有关XferMode的例子可以参考xfermode.cpp、xfermode2.cpp、xfermode3.cpp、sampleXfermode.cpp。
总结
- skia draw
- skia draw bitmap flow
- skia draw path flow
- Draw
- Draw
- Draw
- DRAW
- porting skia
- Skia API
- google skia
- SKIA 编译
- skia简介
- skia简介
- SKIA介绍
- skia入门
- Skia overview
- skia DrawLooper
- OWNER DRAW / CUSTUM DRAW
- python dist-packages 和 site-packages
- oracle学习笔记 ---- 常用SQL*PLUS命令(二)之格式化查询结果
- AS3 相关(2)
- 栈初始化
- PLSQL快捷设置
- skia draw
- C-------数组
- splay模板
- 如何获得android系统已使用的内存
- hdu 2276 Kiki & Little Kiki 2矩阵快速幂
- C++智能指针
- mini2440 X35 移植LCD驱动
- 数字反转
- 1. jQuery 简介