使用SkBitmap作为SkCanvas后端绘图时画不出来的问题
用默认条件在采用了Intel Pentium CPU的PC上编译Skia(参见Windows下从源码编译Skia)后,采用SkBitmap作为SkCanvas的后端来绘图时,遇到了奇怪问题:“无论画什么,跟没画一个样”。
代码如下:
SkImageInfo ii = SkImageInfo::Make(480, 320, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
bitmap.allocPixels(ii, ii.minRowBytes());
SkCanvas canvas(bitmap);
经过试验,发现采用下面的代码可以绘制成功:
SkImageInfo ii = SkImageInfo::Make(480, 320, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
bitmap.allocPixels(ii, ii.minRowBytes());
SkCanvas canvas(bitmap);
所以我觉得可能是颜色类型的问题。就一路跟下去,搞了很久也没搞明白……SkCanvas的绘图源码,一层套一层,看起来比较艰辛……没看进去,中间绕道通过将SkCanvas绘制好的SkBitmap的像素手动转换为RGBA达到了目的。不过如果图片大,逐像素转换就很慢……容易的路总是有后患……
SkBitmapDevice与kN32_SkColorType
骨头还是得啃。我确认了使用SkBitmap作为SkCanvas的后端时,比如上面的代码,实际上SkCanvas自己分配了一个SkBitmapDevice来作为绘图设备,绘图操作会递交给SkBitmapDevice来完成。
SkBitmapDevice在创建绘图设备时校验了拿到的SkBitmap对象的SkImageInfo属性,对其中的Alpha Type和Color Type做了检查。
SkBitmapDevice(SkBitmapDevice.cpp)的构造函数内部会调用valid_for_bitmap_device(),而valid_for_bitmap_device()方法,根据传入的SkImageInfo(就是创建SkBitmap时设定的那个SkImageInfo)做了过滤,只针对kAlpha_8_SkColorType、kRGB_565_SkColorType、kN32_SkColorType三种颜色类别创建SkBitmapDevice,而kN32_SkColorType==kBGRA_8888_SkColorType所以,我设定颜色为kRGBA_8888_SkColorType时,创建出来的SkBitmapDevice是无效的,所以怎么绘制都无效。
valid_for_bitmap_device()的代码如下:
static bool valid_for_bitmap_device(const SkImageInfo& info,
SkAlphaType* newAlphaType) {
if (info