星期一, 6月 29, 2009

Skia and framebuffer

根據 Jserv 大的淺談 Google Skia 圖形處理引擎,得知 skia 只能畫在 Memory buffer 上,那麼,可以直接畫在 Framebuffer 上嗎??

Jserv 大文章裡的例子,SkBitmap 得先呼叫 allocPixels() 來配置所需要的 Memory buffer,根據 SkBitmap.h 裡的宣告,allocPixels 事實上是使用 allocator 來配置所需要的 Memory buffer,如果未指定,會以 stdalloc(HeapAllocator) 來進行配置。因此如果要直接使用 framebuffer,可以繼承 SkBitmap::Allocator 類別之後,改寫 allocPixelRef() 來達到目的。

大致的代碼就像這樣子:

#include "SkTypes.h"
#include "SkRefCnt.h"
#include "SkBitmap.h"
#include "SkDevice.h"
#include "SkPaint.h"
#include "SkRect.h"
#include "SkMallocPixelRef.h"

class FrameBufferAllocator: public SkBitmap::Allocator
{
public:
FrameBufferAllocator();
virtual ~FrameBufferAllocator();
virtual bool allocPixelRef(SkBitmap*, SkColorTable*);
private:
char* m_addr;
int fd;
};

FrameBufferAllocator::FrameBufferAllocator()
{
}

FrameBufferAllocator::~FrameBufferAllocator()
{
// munmap framebuffer pointer.
// close the framebuffer device we opened
}

bool FrameBufferAllocator::allocPixelRef(SkBitmap* dst, SkColorTable* ctable)
{
size_t size = dst->getSize();

// open framebuffer
fd = open( "/dev/fb0", O_RDWR );

// setup framebuffer device via ioctl.

// mmap framebuffer
m_addr = (char *)mmap(0, screensize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

// call original procedures in HeapAllocator::
dst->setPixelRef(new SkMallocPixelRef(m_addr, size, ctable))->unref();
dst->lockPixels();
return true;
}


接著,Jserv 大的範例只要修改一行:

bitmap.allocPixels( new FrameBufferAllocator, NULL );


就可以順利運作了。

p.s. 在 link libskia.a 時,遇到很鳥的狀況,skia 的 Makefile 在製作時,是直接以帶有路徑的 .o 去作,而我 toolchain 的 gcc 居然無法處理,必須要以沒有路徑的 .o 去重新製作,這樣才能 link 成功。

16 則留言:

匿名 提到...

您好

你可以告訴我test-skia.c加上framebuffer的程式碼是如何編譯的嗎??

謝謝!!

elleryq 提到...

用 C/C++ compiler 搭配 make

匿名 提到...

您好

請問您知道如何將一張jpeg的圖,經過解碼後影像輸出至framebuffer?

謝謝!!!

elleryq 提到...

我記得 libjpeg 的 source code 裡就有 example,你可以到 http://www.ijg.org/ 下載 source code。

匿名 提到...

您好

依據Jserv的SKIA範例中是透過繪圖的API且輸出編碼成一張png格式圖檔.

請問我怎饃使用SKIA的API讀取png的圖檔,經過解碼後輸出至FRAMEBUFFER?

THX

elleryq 提到...

先用 SkImageDecoder::DecodeFile 解,然後應該會得到 SkBitmap

接著就可以套本文的範例。

匿名 提到...

您好


以下是我主程式的部份

int main()
{

bitmap.setConfig(SkBitmap::kRGB_565_Config,320,240);

bitmap.allocPixels( new FrameBufferAllocator, NULL );

SkImageDecoder::DecodeFile("pngtest.png", &bitmap);

SkCanvas canvas(new SkDevice(bitmap));

canvas.drawBitmap(bitmap,0,0,NULL);

return 0;
}

編譯完成之後執行發現解碼完的資料沒有寫到framebuffer,你能告訴我程式哪邊有誤還是少了哪些程序?

PS:先前我有測試過 SkImageDecoder::DecodeFile 及 SkImageEncoder::EncodeFile 是可以正常work.

THX

elleryq 提到...

1. 要存取 /dev/fb0,權限要夠
2. 你的顯示是 RGB565 嗎?也就是一個點兩個 byte 嗎?
3. 一個 bitmap 當 framebuffer,你最好 allocate 另外一個 SkBitmap 來放 decode 的結果,最後再畫到 framebuffer 的那個 bitmap 上。從你程式看來是只有一個 SkBitmap...

匿名 提到...

您好

感謝您的回應

1./dev/fb0的權限ok 我有使用您的改成framebuffer範例跑過繪圖範例可以顯示在螢幕上
2.目前我的硬體支援影像格式是使用rgb565,每一個pixel是16bits
3.你意思說我需要使用2個SkBitmap,分別各給decode(bitmap0)及framebuffer(bitmap2)使用,那請問使用哪種api將decode(bitmap0)繪圖至framebuffer(bitmap2)上呢 ?

謝謝 !!!

elleryq 提到...

就大致跟你前面程式一樣,只是要改一下

SkBitmap* pngBitmap=NULL;
SkImageDecoder::DecodeFile("pngtest.png", &pngBitmap);

SkCanvas canvas(new SkDevice(bitmap));

canvas.drawBitmap(pngBitmap,0,0,NULL);

匿名 提到...

您好

非常感謝您的回應

我的問題已經解決,知道自己出錯的問題所在

請問你有使用skia的api可以正常顯示中文字型嗎?

我目前使用wp110-05.ttf字型檔顯示起來有點不正常.....


謝謝 !!!

elleryq 提到...

所以是什麼問題??可以分享一下嗎?

試過文泉驛或是Android提供的Droid字型嗎?

匿名 提到...

您好

我使用的字型不是android提供的,是從在網路上下載用來測試,也不知道是否可以正常使用.

目前我不是使用完整的android套件,只是使用skia 2D graphics engine而已,看看它圖形介面顯示的狀況.

請問android有支援哪些中文字型檔呢?

謝謝 !!!

elleryq 提到...

ttf 跟 ttc 應該都沒有問題才是...

匿名 提到...

您好

以下是我測試中英文字型的部份程式碼

SkPaint paint;
.
.
.
SkTypeface *font = SkTypeface::CreateFromFile("./font/wt014.ttf");

if ( font )

{

paint.setARGB(255, 255, 0, 0);

paint.setTypeface(font);

paint.setTextSize(24);

canvas.drawText("歡迎觀臨SKIA >>>>",40,50,100, paint);
canvas.drawText("hello world ....",30,10,200, paint);
canvas.drawText("HELLO WORD !!!",30,20,400, paint);


}

關於中文字型顯示方面,使用不同的字型所顯示的結果會不一樣,如WCL-02.ttf,WT005.ttf,WTS43.ttf及WP010-05.ttf等都能正常顯示中英文.其他如wp110-05.ttf,WP210-08.ttf會出現漏中文字的問題.
請問你有遇到類似的問題嗎???

謝謝!!!

elleryq 提到...

那應該是字型的問題了~
就請避免使用那些字型...