type
status
date
slug
summary
tags
category
icon
password
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
  1. 分配内存
绘制的结果如下:
notion image
 
notion image

源码地址

写个简单的短链接服务Skia的编译
姜康
姜康
一个软件工程师
公告
type
status
date
slug
summary
tags
category
icon
password
🎉博客网站重新制作了🎉
👏欢迎更新体验👏