1 Skia 繪圖概述
Skia 是 Google 一個底層的圖形、文本、映像、動畫等多方面的圖形庫,是 Android 中圖形系統的引擎。 Skia 作為第三方軟體放在 external 目錄下: external/skia/ 。 skia 的源檔案及部分標頭檔都在 src 目錄下,匯出的標頭檔在 include 目錄下。
使用 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,320,240);
bitmap.allocPixels();
SkCanvas canvas(new SkDevice(bitmap));
SkPaint paint;
// draw points with red.
paint.setARGB(255, 255, 0, 0);
paint.setStrokeWidth(4);
canvas.drawPoint(40,30, paint);
canvas.drawPoint(80,60, paint);
canvas.drawPoint(120,90, paint);
//draw a line with green.
paint.setARGB(255, 0, 255, 0);
paint.setStrokeWidth(4);
canvas.drawLine(160,10,320,110,paint);
//draw a circle with bule.
paint.setARGB(255, 0, 0, 255);
canvas.drawCircle(80,180,50,paint);
//draw text with red
SkTypeface *font = SkTypeface::CreateFromFile("simkai.ttf");
if ( font )
{
paint.setARGB(255, 255, 0, 0);
paint.setTypeface( font );
paint.setTextSize(24);
canvas.drawText("HELLO!:)", 8, 200, 180, paint);
}
SkImageEncoder::EncodeFile("snapshot.png", bitmap,SkImageEncoder::kPNG_Type,100);
return 0;
}
程式執行後,得到如下輸出結果:
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 = -1;
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,100);
cout<< "encode data to png result = "<< ret<< endl;
return 0;
}
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