skia中的SkBitmap


SkBitmap是一个二维的光栅化像素数组.

SkImageInfo

SkImageInfo包含以下信息:

  • 整形的宽,高

    这里的宽可以认为是图像的列数,即 column count

    这里的高可以认为是图像的行数,

  • 用于描述像素格式的SkColorType和SkAlphaType类型

  • 用于描述颜色范围的SkColorSpace

有以下几种静态构造方法:

  • Make(int width, int height, SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs = nullptr)

    传入的参数就是宽,高,颜色类型,透明度类型,颜色空间

    这里的颜色空间cs是一个可选参数,如果颜色空间为null,默认的颜色空间则是sRGB.

  • MakeN32(int width, int height, SkAlphaType at, sk_sp<SkColorSpace> cs = nullptr)

    颜色类型指定为kN32_SkColorType,即kRGBA_8888_SkColorType.

  • MakeN32Premul(int width, int height, sk_sp<SkColorSpace> cs = nullptr)

    颜色类型为kN32_SkColorType,透明度类型为kPremul_SkAlphaType

    Premul是单词premultiplied(预乘)的简称,即RGB分量的值其实已经和alpha相乘过了.

  • MakeA8(int width, int height)

颜色类型是kAlpha_8_SkColorType,即像素+ alpha共8位,透明度类型为kPremul_SkAlphaType;

  • MakeUnknown(int width, int height)

    颜色类型和透明度类型都不设置的情况.

SkAlphaType

enum SkAlphaType {
    kUnknown_SkAlphaType,                          //!< uninitialized
    kOpaque_SkAlphaType,                           //!< pixel is opaque
    kPremul_SkAlphaType,                           //!< pixel components are premultiplied by alpha
    kUnpremul_SkAlphaType,                         //!< pixel components are independent of alpha
    kLastEnum_SkAlphaType = kUnpremul_SkAlphaType, //!< last valid value
};

看定义其实就知道,就这几种类型.

  • kOpaque_SkAlphaType

    透明度为1.0,即完全不透明

为SkBitmap分配内存

SkBitmap一般调用以下几种方法进行内存分配:

  • allocPixels()

  • allocPixels(const SkImageInfo& info, size_t rowBytes)

    如果使用了这个方法,就不需要提前使用setInfo()方法设置SkImageInfo了,第二个参数即行字节数,也就是高度 * 每个像素包含的字节数,传入的值应该等于真实值或者比真实值稍大.

  • tryAllocPixels(const SkImageInfo& info)

上面几种分配方法其实都是使用的 HeapAllocator进行分配的.

基本使用

SkBitmap的作用比较多,在Skia应用代码中比较常见.

这里说一下最基本的使用场景: 创建一个SkBitmap,并用它作为SkCanvas的载体.

#include "demo.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkColor.h"
#include "utils/file_utils.h"

void drawDemoAlt() {
    SkBitmap bitmap;
    bitmap.setInfo(SkImageInfo::MakeN32(640, 640, kOpaque_SkAlphaType));
    bitmap.allocPixels();

    SkCanvas offscreen(bitmap);
    offscreen.clear(SK_ColorWHITE);

    SkPaint paint;
    paint.setAntiAlias(true);
    // 等分绘制圆形,颜色也按照规律改变
    for (int i = 0; i <= bitmap.width(); i = i + bitmap.width() / 10) {
        for (int j = 0; j <= bitmap.height(); j = j + bitmap.height() / 10) {
            float rRatio = (float) i / (float) bitmap.width();
            float gRatio = (float) j / (float) bitmap.height();
            float bRatio = (float) (i + j) / (float) (bitmap.width() + bitmap.height());
            paint.setColor(SkColorSetRGB(255 * rRatio, 255 * gRatio, 255 * bRatio));
            offscreen.drawCircle(i, j, 16, paint);
        }
    }
    saveBitmapAsPng("bitmap_allocPixels_alt.png", bitmap);
}

/*
 * 创建Bitmap的方法
 */
void drawDemo() {
    //创建Bitmap
    SkBitmap bitmap;
    SkImageInfo imageInfo = SkImageInfo::MakeN32(600, 320, kOpaque_SkAlphaType);
    bitmap.allocPixels(imageInfo, imageInfo.width() * imageInfo.bytesPerPixel());

    //Canva绘制
    SkCanvas offscreen(bitmap);
    offscreen.clear(SK_ColorWHITE);
    SkPaint paint;
    paint.setStrokeWidth(2);
    paint.setAntiAlias(true);
    paint.setColor(SK_ColorRED);
    for (int y : {100, 200, 300, 400, 500}) {
        offscreen.drawLine(0, y, 600, y, paint);
    }
    // 保存文件
    saveBitmapAsPng("bitmap_allocPixels.png", bitmap);
}

上面的demo展示了两种Bitmap创建的方法,基本套路都是一样的:

  1. 设置SkImageInfo
  2. 分配内存

绘制的结果如下:

SkBitmap Demo 01

bitmap_allocPixels_alt

源码地址

SkiaFly


文章作者: 姜康
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 姜康 !
评论
 上一篇
skia-基本图形的绘制 skia-基本图形的绘制
skia的图形绘制API和我们平时使用的各种平台的Canvas API几乎没什么区别. 看名字一般也就能知道具体是什么绘制操作了. 例子#include "demo.h" #include "include/core/SkBitmap.h"
2021-03-21
下一篇 
CameraX的简单使用 CameraX的简单使用
基本说明目前CameraX已经处于RC(Release Candidate)阶段了,意味着API不会有大的改动了,官方提示可以应用在实际产品中了. CameraX对之前的Camera2进行了包装,重新设计了API,让开发者可以更简单,更快速
2021-01-24
  目录