Android Skia和2D图形系统 .
Android Skia 和 2D 图形系统
1 Skia 概述
Skia 是 Google 一个底层的图形、图像、动画、 SVG 、文本等多方面的图形库,是 Android 中图形系统的引擎。
Skia 作为第三方软件放在 external 目录下: external/skia/ 。
Skia 的结构如下图所示:
主要包含三个库:
libcorecg.so: 包含 /skia/src/core 的部分内容,比如其中的 Region , Rect 是在 SurfaceFlinger 里面用来计算可视区域的;
libsgl.so: 包含 /skia/src/core|effects|images|ports|utils 的部分和全部内容,这个实现了 skia 大部分的图形效果,以及图形格式的编解码;
libskiagl.so: 包含 /skia/src/gl 里面的内容,主要用来调用 opengl 实现部分效果。
2 Skia 对上层的接口( API )
skia 的源文件及部分头文件都在 external/skia/src 目录下,导出的头文件在 external/skia/include 目录下。最主要的是 SKCanvas 类,几乎整个 Android GUI 系统的底层绘制都是由这个类来完成的。其头文件和源代码文件的路径分别为: external/skia/include/core/SKCanvas.cpp
external/skia/include/core/SKCanvas.h
SKCanvas 类主要有三种绘制功能:
a 基本图形绘制 ( 如 drawARGB,drawLine 函数 )
b 图像文件绘制( drawBitmap 函数)
c 文本绘制( drawText 函数)
3 Skia 的图像编解码部分
这部分的接口主要是:
external/include/image/SKImageDecoder.h // 把图像文件或者流解码到 skia 的内部内存 SKBitmap 中 ;
external/include/image/SKImageEncoder.h // 把 skia 内部内存 SKBitmap 编码成文件或流的形式;
这些接口需要具体的类实现,主要代码在 src/image 文件中。
4 Android 图形系统的 JNI 接口
主要提供了从 Skia 底层库到 Java 上层的支持,代码路径为:
frameworks/base/core/jni/android/graphic/
主要为 Canvas.cpp 文件。
5 Android 的图形包( graphics )
Android 图形类的包是 android.graphics, 它通过调用图形系统的 JNI 提供了对 Java 框架中图形系统的支持,在 Android 的 Java 框架中和 Java 应用程序中, 2D 绘制的功能(基本图形、图片文件,文字)也是通过调用它来实现的。代码路径为:
frameworks/base/graphics/java/android/graphics/
其中 Canvas.cpp 文件实现了 Android 图形系统中最重要的一个类 android.graphic.canvas 。
6 Android 2D 图形硬件加速
目前 Android 2D 图形硬件加速主要是通过 copybit 模块来实现, Copybit 是封装在 Android 系统 opengl 软件实现库( libagl )的一部分,仅对 openGL ES 2D API 进行封装,实现 openGL ES 2D API 到硬件的加速功能。
copybit 模块以 HAL 的形式实现,代码 hardware/msm7k/libcopybit/copybit.c
另外,在 http://code.google.com/p/skia/wiki/FAQ 看到关于 Skia 硬件加速和字体支持的相关信息:
Does Skia support HW acceleration?
There are two ways Skia can take advantage of HW.
1. Subclass SkCanvas
Since all drawing calls go through SkCanvas, those calls can be redirected to a different graphics API. SkGLCanvas has been written to direct its drawing calls to OpenGL. See src/gl/
2. Custom bottleneck routines
There are sets of bottleneck routines inside the blits of Skia that can be replace on a platform in order to take advantage of specific CPU features. One such example is the NEON SIMD instructions on ARM v7 devices. See src/opts/
Does Skia support Font hinting?
Skia has a built-in font cache, but it does not know how to actual render font files like TrueType into its cache. For that it relies on the platform to supply an instance of SkScalerContext. This is Skia's abstract interface for communicating with a font scaler engine. In src/ports you can see support files for FreeType, Mac OS X, and Windows GDI font engines. Other font engines can easily be supported in a like manner
Skia API的简单应用
1 Skia 绘图概述
使用 Skia 的 API 进行图形绘制时主要会用到一下几个类:
SkBitmap 、 SkCanvas 、 SkPaint 和 SkRect ,其中 SkBitmap 用来设置像素, SkCanvas 写入位图, SkPaint 设置颜色和样式, SkRect 用来绘制矩形。其实现代码主要在 src/core 目录下。
2 使用 Skia 绘图的步骤
a) 定义一个位图 32 位像素并初始化
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
其中 setConfig 为设置位图的格式,原型为 void setConfig(Config, int width, int height, int rowBytes = 0)
Config 为一个数据结构
enum Config {
kNo_Config, // 不确定的位图格式
kA1_Config, //1 位 ( 黑 , 白 ) 位图
kA8_Config, //8 位 ( 黑 , 白 ) 位图
kIndex8_Config, // 类似 windows 下的颜色索引表,具体请查看 SkColorTable 类结构
kRGB_565_Config, //16 位象素 565 格式位图,详情请查看 SkColorPriv.h 文件
kARGB_4444_Config, //16 位象素 4444 格式位图,详情请查看 SkColorPriv.h 文件
kARGB_8888_Config, //32 位象素 8888 格式位图,详情请查看 SkColorPriv.h 文件
kRLE_Index8_Config,
kConfigCount
};
b) 分配位图所占的空间
bitmap.allocPixels()
其实 allocPixels 为重载函数,原型为 bool allocPixels(SkColorTable* ctable = NULL)
参数 ctable 为颜色索引表,一般情况下为 NULL 。
c) 指定输出设备
SkCanvas canvas(new SkDevice(bitmap));
其中 canvas 为一个多构造函数,原型为
explicit SkCanvas(const SkBitmap& bitmap) ,
explicit SkCanvas(SkDevice* device = NULL)
explicit 关健字的意思为:不允许类型转换
输出设备可以为一个上下文 Device, 也可以指定为一张位图。
d) 设备绘制的风格
Paint paint;
SkRect r;
paint.setARGB(255, 255, 0, 0);
r.set(25, 25, 145, 145);
canvas.drawRect(r, paint);
paint 可以指定绘图的颜色,文本的大小及对齐方式,编码格式等等,因为以前位图的格式设置为 kARGB_8888_Config ,所以这里要设置绘制的颜色 setARGB(255, 255, 0, 0) ,第一位参数为透明颜色通道,其它三位分别为 R 、 G 、 B 。 r 设置要绘制的范围,最后通过 drawRect 绘制出指定区域的一个方形。
这样,一个红色的矩形就绘制成功了。
SkCanvas 主要完成三种绘制功能:
a 基本图形绘制 ( 如 drawARGB,drawLine 函数 )
b 图像文件绘制( drawBitmap 函数)
c 文本绘制( drawText 函数)
相关 API 有:
canvas.drawRect(rect, paint); canvas.drawOval(oval, paint); canvas.drawCircle(x, y, radius, paint); canvas.drawRoundRect(rect, rx, ry, paint); canvas.drawPath(path, paint); canvas.drawBitmap(bitmap, x, y, &paint); canvas.drawBitmapRect(bitmap, &srcRect, dstRect, &paint); canvas.drawBitmapMatrix(bitmap, matrix, &paint); canvas.drawText(text, length, x, y, paint); canvas.drawPosText(text, length, pos[], paint); canvas.drawTextOnPath(text, length, path, paint);
e) 例程
i )画点、线、圆、文字
#include "SkBitmap.h" #include "SkDevice.h" #include "SkPaint.h" #include "SkRect.h" #include "SkImageEncoder.h" #include "SkTypeface.h" using namespace std; int main() { SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config,,); bitmap.allocPixels(); SkCanvas canvas(new SkDevice(bitmap)); SkPaint paint; // draw points with red. paint.setARGB(, , , ); paint.setStrokeWidth(); canvas.drawPoint(,, paint); canvas.drawPoint(,, paint); canvas.drawPoint(,, paint); //draw a line with green. paint.setARGB(, , , ); paint.setStrokeWidth(); canvas.drawLine(,,,,paint); //draw a circle with bule. paint.setARGB(, , , ); canvas.drawCircle(,,,paint); //draw text with red SkTypeface *font = SkTypeface::CreateFromFile("simkai.ttf"); if ( font ) { paint.setARGB(, , , ); paint.setTypeface( font ); paint.setTextSize(); canvas.drawText("HELLO!:)", , , , paint); } SkImageEncoder::EncodeFile("snapshot.png", bitmap,SkImageEncoder::kPNG_Type,); return ; }
程序执行后,得到如下输出结果:
ii) 图像的编解码
该例程目前测试只支持 .png 格式的图片, .jpg 还不支持,还未找到原因。
#include "SkBitmap.h" #include "SkDevice.h" #include "SkPaint.h" #include "SkRect.h" #include "SkImageEncoder.h" #include "SkImageDecoder.h" #include <iostream> using namespace std; int main() { int ret = -; SkBitmap bitmap; //SkImageDecoder ret = SkImageDecoder::DecodeFile("./old.png", &bitmap); cout<< "get the decode type = "<< bitmap.config() << endl; //SkImageEncoder ret = SkImageEncoder::EncodeFile("new1.png",bitmap,SkImageEncoder::kPNG_Type,); cout<< "encode data to png result = "<< ret<< endl; return ; }
SkImageDecoder::DecodeFile("./old.png", &bitmap);
将 png 转换成位图格式,并将数据放到 bitmap 变量中
SkImageEncoder::EncodeFile("snapshot.png", bitmap,SkImageEncoder::kPNG_Type,/* Quality ranges from 0..100 */ 100);
将 bitmap 中的数据编码输出为 .png 格式,第一位参数为 png 文件路径,第二位为指定的输出位图,第三位为文件的类型,第四位参数指定了输出位图的质量,范围为 0..100 ,默认为 80 。
3 图形图像特效
src/effects 目录的文件主要实现一些图形图像的特效,包括 遮罩、浮雕、模糊、滤镜、渐变色、离散、透明以及 PATH 的各种特效等。
4 动画
src/animator 目录的文件主要实现了 Skia 的动画效果,Android不支持。
5 界面 UI 库
src/view 目录 构建了一套界面 UI 库。
组件包括 Window,Menu, TextBox, ListView, ProgressBar, Widget, ScrollBar,TagList,Image 等。
6 其它
a) src/gl 目录: 这部分是 skia 调用 OpenGL 或 OpenGL ES 来实现 3D 效果。
如果定义了 MAC ,则使用 OpenGL ,如果定义了 Android ,则使用嵌入式 系统上的 esgl 三维图形库。
b)src/images 目录: 主要是 SkImageDecoder 和 SkImageEncoder 以及 SkMovie 。主要是用来处理 images 的,能处理的图像类型包括: BMP 、
JPEG/PVJPEG 、 PNG 、 ICO ,而 SkMovie 是用来处理 gif 动画的。
c) src/opts 目录:性能优化的代码。
d) src/pdf 目录: 处理 PDF 文档,用了一个 fpdfemb 库。
e) src/ports 目录: 这部分是 skia 的一些接口在不同系统上的实现,平台相关的代码,比如字体、线程、时间等, 主要包括几个部分: Font , Event , File , Thread , Time , XMLParser
这些与 Skia 的接口,需要针对不同的 操作系统实现。
f) src/svg 目录: 矢量图像,Android不支持。
SkSVGPath, SkSVGPolyline, SkSVGRect, SkSVGText, SkSVGLine, SkSVGImage, SkSVGEllipse 等等。
g) src/text 目录:???
h) src/utils 目录: 是一些辅助工具类。
SkCamera, SkColorMatrix,SkOSFile,SkProxyCanvas,SkInterpolator 等文件。
i) src/xml : 这是处理 xml 数据的部分, skia 在这里只是对 xml 解析器做了一层包装,具体的 xml 解析器的实现需要根据不同的操作系统及宿主程序来实现。
j) Third-party library
除了自身的所有文件外, skia 还使用了一些 third-party library 以及包含了不少 linux上的头文件。
通过分析 skia 源程序,发现 skia 主要使用以下几个第三方库:
Zlib ,处理数据的压缩和解压缩
Jpeglib ,处理 jpeg 图像的编码解码
Pnglib ,处理 png 图像的编码解码
giflib ,处理 gif 图像
fpdfemb ,处理 pdf 文档
skia 还需要一些 linux/unix 下的头文件(可能还需要更多):
stdint.h
unistd.h
features.h
cdefs.h
stubs.h
posix_opt.h
types.h
wordsize.h
typesizes.h
confname.h
getopt.h
mman.h
Android Skia和2D图形系统 .的更多相关文章
- <2014 05 14> Android平台下2D/3D开发攻略
Android通过OpenGL包含了对高性能2D和3D图形的支持,尤其支持OpenGLES API.OpenGL是一个跨平台的图形API,提供了软件操作3D图形硬件的接口.OpenGLES是一个专用于 ...
- Android图形子系统
图形操作可以有两种方式实现:一是利用通用CPU模拟图形操作:二是利用GPU专门做图形操作.前者会增加CPU的负担,在现在高分辨率已经是普遍现象的时候,让通用处理器来完成大量的图形计算已经不现实.And ...
- android技术牛人的博客[转]
Android+JNI调用–文件操作 开发环境:Windows xp sp3 +MyEclipse 8.6+android2.3.3+jdk1.6+android-ndk-r6b JNI概述: ...
- Android游戏引擎总汇 原文出处:http://software.intel.com/en-us/blogs/2012/03/13/game-engines-for-android?page=1
随着Android系统的使用越来越广泛,了解一下Android平台下的游戏引擎就非常有必要.而同时因为基于Intel x86的移动设备越来越多,我也非常关注支持x86的移动游戏引擎.然而就目前为止游戏 ...
- 【转】Pro Android学习笔记(一):Android 平台 2013.6.4
本系列是阅读<Pro Android4>的读书笔记,也包括网络阅读资料的整理,以及个人心得. 由于智能手机引入AP(应用处理器),Android在某种意义上是个人计算机,具有桌面计算机的完 ...
- Android 8.1 关机充电动画(三)Android模式
system:Android 8.1 platform:RK3326/PX30 uboot kernel system/core/healthd Android 8.1 关机充电动画(一)模式选择 A ...
- Android浏览图片,点击放大至全屏效果
做到照片浏览的功能,对于QQ空间中点击图片放大至全屏,感觉效果很赞,于是也做了个类似的效果.如下. 我不知道QQ那个是怎么做的,我的思路如下: 首先,从图片缩略界面跳转到图片详情页面,应该是从一个Ac ...
- Android 中图片压缩分析(上)
作者: shawnzhao,QQ音乐技术团队一员 一.前言 在 Android 中进行图片压缩是非常常见的开发场景,主要的压缩方法有两种:其一是质量压缩,其二是下采样压缩. 前者是在不改变图片尺寸的情 ...
- Benchmark Test On Android Devices
一.Android设备上的Benckmark测试概述 同PC相比,在Android设备上的性能测试还没有一个公认的标准.也没有PC上那么多的测试程序集.但我们可以通过一些工具所得到的信息更好的了解设备 ...
随机推荐
- 【Python@Thread】queue模块-生产者消费者问题
python通过queue模块来提供线程间的通信机制,从而可以让线程分项数据. 个人感觉queue就是管程的概念 一个生产者消费者问题 from random import randint from ...
- putty命令行提交本地修改文件到git
使用putty 连接 linux服务器 ,服务器账户和密码在putty 上使用git提交.使用git账户和密码 (需要升级管理员) 01 pwd 查看当前目录print work directory0 ...
- OpenLayer
<html> <head> <meta charset="utf-8"> <title>GIS开发样例-V1.0</title ...
- 创建透明CEdit控件
1.在资源编辑器中将Edit控件的Border设为none(当然也可以在代码中修改窗口样式) 2.在重载CEdit的类中响应MSG_OCM_CTLCOLOREDIT消息,在处理函数中将背景模式设为透明 ...
- Chapter 14_4 使用_ENV
因为_ENV是一个普通的变量,我们可以像其他变量一样去对它进行赋值和访问. _ENV = nil 上面的赋值操作,将会使得在它之后的代码块不能直接访问全局变量.不过,对控制你的代码所使用的变量有用处. ...
- MySQL5.6新特性Index conditontion pushdow
index condition pushdown是MySQL5.6的新特性,主要是对MySQL索引使用的优化. Index condition push简称ICP,索引条件下推,将索引条件从serve ...
- WPFbutton样式
有四款button不同的风格 <Window x:Class="SjglzxRj.Window3" xmlns="http://schemas.microsoft. ...
- PHP验证码类
通过PHP的GD库图像处理内容,设计一个验证码类Vcode.将该类声明在文件vcode.class.php中,并通过面向对象的特性将一些实现的细节封装在该类中.只要在创建对象时,为构造方法提供三个参数 ...
- mongoDB5--mongoDB增删改查
之前我们探讨了mongodb的"增删改查",要知道,我们的增删改其实都离不开查询表达式,所以查询表达式在mongodb是非常重要的.关于查询其实我们只是介绍了以小部分.关于mong ...
- tomcat各目录(文件)作用
以tomcat7.0.50为例,主目录下有bin,conf,lib,logs,temp,webapps,work 7个文件夹 bin目录主要是用来存放tomcat的命令,主要有两大类,一类是以.sh结 ...