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创建的方法,基本套路都是一样的:
- 设置SkImageInfo
- 分配内存
绘制的结果如下:
源码地址
- 作者:姜康
- 链接:https://jiangkang.tech/article/a4dccf54-8727-4add-8235-32d0ee68d87a
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章