文章目录
- SKBitMap方法
- CanCopyTo 是否可复制为指定颜色类型
- Copy 深拷贝
- Copy(SKColorType) 深拷贝为指定颜色类型
- CopyTo(SKBitmap) 深拷贝
- CopyTo(SKBitmap, SKColorType) 深拷贝
- Decode 解码内容
- DecodeBounds 解码图像信息
- Encode 编码
- Erase 清除图像
- ExtractAlpha 提取透明通道
- ExtractSubset提取子图像
- GetAddress 获取指定像素的内存地址
- GetPixel 获取指定像素的颜色
- GetPixels 获取像素内存地址
- GetPixelSpan 获取像素字节数组
- InstallMaskPixels 像素转Alpha位图(蒙版)
- InstallPixels 像素转位图
- NotifyPixelsChanged 修改通知
- PeekPixels 获取图像信息
- Reset 重置
- Resize 缩放
- ScalePixels 缩放
- SetPixel/SetPixels 设置像素
- ToShader 转为着色器
- TryAllocPixels 尝试分配内存
SKBitMap方法
CanCopyTo 是否可复制为指定颜色类型
public bool CanCopyTo (SkiaSharp.SKColorType colorType);
判断是否可以将当前颜色类型转换为指定颜色类型。
Copy 深拷贝
public SkiaSharp.SKBitmap Copy ();
复制并返回一个SKBitmap对象。
Copy(SKColorType) 深拷贝为指定颜色类型
public SkiaSharp.SKBitmap Copy (SkiaSharp.SKColorType colorType);
复制为指定颜色类型的SKBitmap对象。
CopyTo(SKBitmap) 深拷贝
public bool CopyTo (SkiaSharp.SKBitmap destination);
复制到指定SKBitmap对象,并返回是否成功。
CopyTo(SKBitmap, SKColorType) 深拷贝
public bool CopyTo (SkiaSharp.SKBitmap destination, SkiaSharp.SKColorType colorType);
复制为指定颜色类型到指定SKBitmap对象,并返回是否成功。
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
using (var paint = new SKPaint())
{
paint.TextSize = 18;
paint.Typeface = SKTypeface.FromFamilyName("黑体");
paint.Color = SKColors.Green;
using(var bgraBtmp=new SKBitmap(100,100, SKColorType.Bgra8888, SKAlphaType.Premul))
{
using (var bCanvas = new SKCanvas(bgraBtmp))
{
bCanvas.DrawRect(new SKRect(10, 20, 90, 80), paint);
canvas.DrawBitmap(bgraBtmp, 20, 20, paint);
canvas.DrawText($"原图,矩形无圆形", 20, 20, paint);
using (var copyBmp = bgraBtmp.Copy())
{
paint.Color = SKColors.Blue;
bCanvas.DrawCircle(bgraBtmp.Width / 2, bgraBtmp.Height / 2, bgraBtmp.Width / 4, paint);
canvas.DrawBitmap(copyBmp, 450, 20, paint);
canvas.DrawText($"复制原图,后在原图上画圆", 450, 20, paint);
}
}
using (var rgbaBmp = new SKBitmap())
{
if (bgraBtmp.CanCopyTo(SKColorType.Rgba8888))
{//可以复制
bgraBtmp.CopyTo(rgbaBmp, SKColorType.Rgba8888);
canvas.DrawBitmap(rgbaBmp, 20, 120, paint);
canvas.DrawText($"复制带圆的原图转RGBA", 20, 120, paint);
}
if(rgbaBmp.CanCopyTo(SKColorType.Gray8))
{//可以复制
using (var grayBmp = new SKBitmap(100, 100, SKColorType.Gray8, SKAlphaType.Premul))
{
rgbaBmp.CopyTo(grayBmp, SKColorType.Gray8);
canvas.DrawBitmap(grayBmp, 20, 240, paint);
canvas.DrawText($"复制带圆的原图转Gray", 20, 240, paint);
}
}
}
}
}
图像为深拷贝,修改原图,不影响复制后的图像。
Decode 解码内容
Decode(string)
public static SkiaSharp.SKBitmap Decode (string filename);
可使用相对或绝对路径
//支持中文,直接读取图像文件,正常,返回SKBitmap对象
var skBmp = SKBitmap.Decode(@"Images\中文路径\AIWomanBig.png");
//支持中文,直接读取图像文件,正常,返回SKBitmap对象
var skBmp = SKBitmap.Decode(@"D:\Images\中文路径\AIWomanBig.png");
注意,加载解码图像文件时:
- 解码不成功时,返回null,不报错。
- 图像文件不存在时,返回null,不报错。
Decode(Byte[])
public static SkiaSharp.SKBitmap Decode (byte[] buffer);
public static SkiaSharp.SKBitmap Decode (ReadOnlySpan<byte> buffer);
解码图像字节数组。
//先获取文件字节,再解码字节数组。正常,返回SKBitmap对象
byte[] fileBytes = File.ReadAllBytes(@"Images\中文路径\AIWomanBig.png");
skBmp = SKBitmap.Decode(fileBytes);
skBmp.Dispose()
;
//异常,fileBytes不可以为null
fileBytes = null;
if (fileBytes != null)
{
skBmp = SKBitmap.Decode(fileBytes);
}
try
{
fileBytes = new byte[] { 0x01, 0x02 };
skBmp = SKBitmap.Decode(fileBytes);
}
catch (Exception ex)
{
;//报“值不能为null”
}
注意:
- 传入的字节数组为空或解码失败时,报异常。
Decode(Stream)
public static SkiaSharp.SKBitmap Decode (System.IO.Stream stream);
using (var stream = new FileStream(@"Images\中文路径\AIWomanBig.png", FileMode.Open))
{
skBmp = SKBitmap.Decode(stream);
skBmp.Dispose();
}
using (var stream = File.OpenRead(@"Images\中文路径\AIWomanBig.png"))
{
skBmp = SKBitmap.Decode(stream);
skBmp.Dispose();
}
using (var stream = File.OpenRead(@"Images\notImg.png"))
{//文件读取成功,但非图像
//返回null,不报错
skBmp = SKBitmap.Decode(stream);
}
- 解码成功时,返回SKBitmap对象
- 解码失败时,返回null,不报错。
Decode(SKStream)
public static SkiaSharp.SKBitmap Decode (SkiaSharp.SKStream stream);
使用SKStream解码图像
// 打开文件并创建流
using (FileStream fileStream = new FileStream(@"Images\AIWomanBig.png", FileMode.Open, FileAccess.Read))
{
// 将 FileStream 转换为 SKManagedStream
using (SKManagedStream skStream = new SKManagedStream(fileStream))
{
// 使用 SkiaSharp 解码图像
skBmp = SKBitmap.Decode(skStream);
skBmp.Dispose();
}
}
// 打开文件并创建流
using (FileStream fileStream = new FileStream(@"Images\notImg.png", FileMode.Open, FileAccess.Read))
{
// 将 FileStream 转换为 SKManagedStream
using (SKManagedStream skStream = new SKManagedStream(fileStream))
{
// 非图像,解码失败,返回null,不报错
skBmp = SKBitmap.Decode(skStream);
;
}
}
- 解码成功时,返回SKBitmap对象
- 解码失败时,返回null,不报错。
Decode(SKData)
public static SkiaSharp.SKBitmap Decode (SkiaSharp.SKData data);
// 打开文件并创建流
using (FileStream fileStream = new FileStream(@"Images\AIWomanBig.png", FileMode.Open, FileAccess.Read))
{
// 将 FileStream 转换为 SKManagedStream
using (var skData = SKData.Create(fileStream))
{
// 使用 SkiaSharp 解码图像
skBmp = SKBitmap.Decode(skData);
skBmp.Dispose();
}
}
// 打开文件并创建流
using (FileStream fileStream = new FileStream(@"Images\notImg.png", FileMode.Open, FileAccess.Read))
{
// 将 FileStream 转换为 SKManagedStream
using (var skData = SKData.Create(fileStream))
{
// 非图像,解码失败,返回null,不报错
skBmp = SKBitmap.Decode(skData);
;
}
}
- 解码成功时,返回SKBitmap对象
- 解码失败时,返回null,不报错。
Decdoe(SKCodec)
public static SkiaSharp.SKBitmap Decode (SkiaSharp.SKCodec codec);
// 打开文件并创建流
using (FileStream fileStream = new FileStream(@"Images\AIWomanBig.png", FileMode.Open, FileAccess.Read))
{
// 将 FileStream 转换为 SKManagedStream
using (var skCodec = SKCodec.Create(fileStream))
{
// 使用 SkiaSharp 解码图像
skBmp = SKBitmap.Decode(skCodec);
skBmp.Dispose();
}
}
// 打开文件并创建流
using (FileStream fileStream = new FileStream(@"Images\notImg.png", FileMode.Open, FileAccess.Read))
{
// 将 FileStream 转换为 SKManagedStream
using (var skCodec = SKCodec.Create(fileStream))
{
try
{
// 非图像,解码失败,异常,报错
skBmp = SKBitmap.Decode(skCodec);
;
}
catch (Exception ex)
{
}
}
}
- 解码成功时,返回SKBitmap对象
- 解码失败时,异常、报错。
Decode(X,SKImageInfo)
按官网的解析应该是,可以通过SKImageInfo来控制图像的缩放和颜色类型的转换,可我在实际测试过程中,只要SKImageInfo与原图像的SKImageInfo对象不一样,都是返回null。不知是Bug,还是调用方法不正确!?
DecodeBounds 解码图像信息
public static SkiaSharp.SKImageInfo DecodeBounds (string filename);
public static SkiaSharp.SKImageInfo DecodeBounds (System.IO.Stream stream);
public static SkiaSharp.SKImageInfo DecodeBounds (ReadOnlySpan<byte> buffer);
public static SkiaSharp.SKImageInfo DecodeBounds (SkiaSharp.SKStream stream);
public static SkiaSharp.SKImageInfo DecodeBounds (SkiaSharp.SKData data);
public static SkiaSharp.SKImageInfo DecodeBounds (byte[] buffer);
调整获取图像信息,不解码具体内容
SKImageInfo imgInfo = SKImageInfo.Empty;
var sw = Stopwatch.StartNew();
var times = 10;
for (int i = 0; i < times; i++)
{
imgInfo = SKBitmap.DecodeBounds(@"Images\AIWoman.png");
}
sw.Stop();
if (imgInfo != SKImageInfo.Empty)
{
canvas.DrawText($"DecodeBounds {times}times:{sw.ElapsedMilliseconds}ms,Img Width:{imgInfo.Width},Height:{imgInfo.Height}", 20, 30, paint);
}
sw.Restart();
for (int i = 0; i < times; i++)
{
skBmp = SKBitmap.Decode(@"Images\AIWoman.png");
}
sw.Stop();
if (imgInfo != SKImageInfo.Empty)
{
canvas.DrawText($"Decode {times}times:{sw.ElapsedMilliseconds}ms,Img Width:{skBmp.Width},Height:{skBmp.Height},", 20, 60, paint);
}
对比Decode与DecodeBounds的速度。
Encode 编码
public SkiaSharp.SKData Encode (SkiaSharp.SKEncodedImageFormat format, int quality);
public bool Encode (SkiaSharp.SKWStream dst, SkiaSharp.SKEncodedImageFormat format, int quality);
public bool Encode (System.IO.Stream dst, SkiaSharp.SKEncodedImageFormat format, int quality);
SKBitmap可以Encode为Jpeg、Png格式,不能直接保存为Gif,Bmp格式?
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
using (var paint = new SKPaint())
{
paint.TextSize = 18;
paint.Typeface = SKTypeface.FromFamilyName("黑体");
int width = 200;
int height = 200;
using (var bmp = new SKBitmap(width, height))
{
using (var sCanvas = new SKCanvas(bmp))
{
sCanvas.Clear(SKColors.White);
using (var sPaint = new SKPaint())
{
sPaint.Color = SKColors.Green;
sPaint.IsAntialias = true;
sCanvas.DrawCircle(bmp.Width / 2, bmp.Height / 2, bmp.Width / 4, sPaint);
}
}
//Encode(SKEncodedImageFormat, Int32)
using (var skData=bmp.Encode(SKEncodedImageFormat.Jpeg,80))
{
using (var stream = File.OpenWrite(@"Images\circle.jpg"))
{
skData.SaveTo(stream);
}
}
//Encode(SKWStream, SKEncodedImageFormat, Int32)
using (var fileStream=File.OpenWrite(@"Images\circle.png"))
{
using (var managedStream = new SKManagedWStream(fileStream))
{
var success = bmp.Encode(managedStream, SKEncodedImageFormat.Png, 100);
if(!success)
{
Console.WriteLine("Encode SKBitmap fail!");
}
}
}
//不支持直接,保存为bmp?SKBitmap转Bitmap
// 将 SKBitmap 转换为 Bitmap
using (var image = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
{
var data = bmp.Bytes;
var bitmapData = image.LockBits(new System.Drawing.Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, image.PixelFormat);
IntPtr pointer = bitmapData.Scan0;
System.Runtime.InteropServices.Marshal.Copy(data, 0, pointer, data.Length); //
image.UnlockBits(bitmapData);
// 将 Bitmap 保存为 BMP 文件
image.Save("Images/circle.bmp", ImageFormat.Bmp);
}
}
}
Erase 清除图像
public void Erase (SkiaSharp.SKColor color);
public void Erase (SkiaSharp.SKColor color, SkiaSharp.SKRectI rect);
填充整个图像或指定矩形区域为指定颜色。
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
using (var paint = new SKPaint())
{
paint.TextSize = 18;
paint.Typeface = SKTypeface.FromFamilyName("黑体");
int width = 200;
int height = 200;
using (var bmp = new SKBitmap(width, height))
{
//将图像填充为LightGreen
bmp.Erase(SKColors.LightGreen);
canvas.DrawBitmap(bmp,20,20, paint);
//将指定矩形区域填充为Red
bmp.Erase(SKColors.Red, new SKRectI(40, 40, 140, 140));
canvas.DrawBitmap(bmp, 320, 20, paint);
}
}
ExtractAlpha 提取透明通道
public bool ExtractAlpha (SkiaSharp.SKBitmap destination);
单独提取Alpha通道作为新的SkBitmap对象。
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
using (var paint = new SKPaint())
{
paint.TextSize = 18;
paint.Typeface = SKTypeface.FromFamilyName("宋体");
paint.FilterQuality = SKFilterQuality.High;
if (skBmp == null) skBmp = SKBitmap.Decode(@"Images\Transparent.png");
// 创建一个 SKPaint 对象,用于模糊处理
paint.ImageFilter = SKImageFilter.CreateBlur(5, 5);
// 提取 alpha 通道并应用模糊滤镜
SKBitmap alphaBitmap = new SKBitmap();
var width = 500;
var height = width * skBmp.Height / skBmp.Width;
if (skBmp.ExtractAlpha(alphaBitmap, paint))
{
// 绘制阴影
canvas.DrawBitmap(alphaBitmap, new SKRect(25, 25, 25 + width, 25 + height), paint); // 阴影位置偏移
}
alphaBitmap.Dispose();
paint.ImageFilter = null;
// 绘制原图像
canvas.DrawBitmap(skBmp, new SKRect(20, 20, 20 + width, 20 + height), paint);
canvas.DrawText($"原图+阴影", 20, 20 + height + 20, paint);
canvas.DrawBitmap(skBmp, new SKRect(20, 40 + height, 20 + width, 40 + height * 2), paint);
canvas.DrawText($"原图", 20, 20 + height*2 + 20, paint);
}
提取原图的Alpha通道,进行模糊后做为原图的阴影。
ExtractSubset提取子图像
public bool ExtractSubset (SkiaSharp.SKBitmap destination, SkiaSharp.SKRectI subset);
从原像中获取指定区域的子图像。一般情况,该子图像与原图像是共享内存的,除非ColorType不支持。
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
using (var paint = new SKPaint())
{
paint.TextSize = 18;
paint.Typeface = SKTypeface.FromFamilyName("宋体");
paint.FilterQuality = SKFilterQuality.High;
if (skBmp == null) skBmp = SKBitmap.Decode(@"Images\AIWoman.png");
SKBitmap subBmp = new SKBitmap();
//提取子图像
if(skBmp.ExtractSubset(subBmp,new SKRectI(1400, 0, 2400,1100)))
{
canvas.DrawBitmap(subBmp, new SKRect(20, 20,320,320), paint);
}
subBmp.Dispose();
canvas.DrawBitmap(skBmp, new SKRect(350,20,750,420), paint);
}
提取子图像并绘制。
GetAddress 获取指定像素的内存地址
public IntPtr GetAddress (int x, int y);
获取指定像素的内存地址。
GetPixel 获取指定像素的颜色
public SkiaSharp.SKColor GetPixel (int x, int y);
获取指定像素的颜色。(注意,大量访问时,效率不高,请改用指针方式)
GetPixels 获取像素内存地址
public IntPtr GetPixels ();
public IntPtr GetPixels (out IntPtr length);
获取图像的像素地址和大小。(如果图像没有任何像素,返回IntPtr.Zero)
大量像素时,使用指针操作,性能更优。
GetPixelSpan 获取像素字节数组
public ReadOnlySpan<byte> GetPixelSpan ();
获取图像的字节数组。
InstallMaskPixels 像素转Alpha位图(蒙版)
public bool InstallMaskPixels (SkiaSharp.SKMask mask);
将指定蒙版的像素安装(赋值)到位图中。(得到的位图只有Alpha通道)
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
using (var paint = new SKPaint())
{
paint.TextSize = 18;
paint.Typeface = SKTypeface.FromFamilyName("宋体");
paint.FilterQuality = SKFilterQuality.High;
if (skBmp == null) skBmp = SKBitmap.Decode(@"Images\AIWoman.png");
// 创建一个掩码图像的数据
int width = 800;
int height = 800;
// 分配掩码数据的非托管内存
IntPtr maskPtr = Marshal.AllocHGlobal(width * height);
try
{
//绘制原图
canvas.DrawBitmap(skBmp, new SKRect(0, 0, width, height), paint);
//渐变透明
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
Marshal.WriteByte(maskPtr, y * width + x, (byte)(255F * (x + y) / (height + width)));
}
}
var mask = new SKMask
{
Image = maskPtr,
Format = SKMaskFormat.A8,
Bounds = new SKRectI(0, 0, width, height),
RowBytes = (uint)width
};
using (var bmp = new SKBitmap(width, height))
{
if (bmp.InstallMaskPixels(mask))
{
paint.BlendMode = SKBlendMode.DstIn;
//绘制半透层
canvas.DrawBitmap(bmp, 0, 0,paint);
}
}
}
finally
{
Marshal.FreeHGlobal(maskPtr);
}
}
定义一个SKMask,赋值为从左上角到右下角的半透掩膜。先绘制原图,再在原图上绘制半透明掩膜。
InstallPixels 像素转位图
public bool InstallPixels (SkiaSharp.SKPixmap pixmap);
public bool InstallPixels (SkiaSharp.SKImageInfo info, IntPtr pixels);
public bool InstallPixels (SkiaSharp.SKImageInfo info, IntPtr pixels, int rowBytes);
public bool InstallPixels (SkiaSharp.SKImageInfo info, IntPtr pixels, int rowBytes, SkiaSharp.SKBitmapReleaseDelegate releaseProc);
用于将现有的像素数据安装到一个 SKBitmap 对象中。
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
// 假设我们有一个已存在的像素数组
int width = 300;
int height = 300;
int bytesPerPixel = 4;
byte[] pixelData = new byte[width * height * bytesPerPixel];
// 填充像素数据
for (int i = 0; i < pixelData.Length; i++)
{
if ((i + 1) % 4 == 0)
{
pixelData[i] = 255;
}
else
{
pixelData[i] = (byte)(i % 256);
}
}
// 创建 SKBitmap 并安装像素数据
SKBitmap bitmap = new SKBitmap();
IntPtr pixelPtr = Marshal.UnsafeAddrOfPinnedArrayElement(pixelData, 0);
// 定义解构函数,当 bitmap 释放时释放内存
SkiaSharp.SKBitmapReleaseDelegate releaseFunction = (addr, context) => { };
// 安装像素数据
bitmap.InstallPixels(new SKImageInfo(width, height), pixelPtr, width * bytesPerPixel, releaseFunction, IntPtr.Zero);
using(var paint=new SKPaint())
{
paint.FilterQuality = SKFilterQuality.High;
paint.BlendMode = SKBlendMode.SrcOver;
canvas.DrawBitmap(bitmap, new SKRect(0,0,width,height),paint);
}
// 不再需要 bitmap 时,释放资源
bitmap.Dispose();
定义并赋值一个字节数组,获取到去指针后通过InstallPixels赋值给SKBitmap对象,并绘制出结果。
NotifyPixelsChanged 修改通知
public void NotifyPixelsChanged ();
向位图的使用者指示像素数据已更改。
使用指针直接修改像素时,调用NotifyPixelsChanged()方法,确保输出SKBitmap对象与实际内容一致。
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
int width = 100;
int height = 100;
int bytesPerPixel = 4;
// 创建一个空的 SKBitmap
SKBitmap bitmap = new SKBitmap(width, height, SKColorType.Rgba8888, SKAlphaType.Premul);
// 获取像素数据指针
IntPtr pixelPtr = bitmap.GetPixels();
// 直接操作像素数据
unsafe
{
byte* pixels = (byte*)pixelPtr.ToPointer();
for (int i = 0; i < width * height * bytesPerPixel; i++)
{
if ((i + 1) % 4 == 0)
{
pixels[i] = 255;
}
else
{
pixels[i] = (byte)(i % 256);
}
}
}
// 通知 SKBitmap 像素数据已经改变
bitmap.NotifyPixelsChanged();
canvas.DrawBitmap(bitmap, 0, 0);
bitmap.Dispose();
PeekPixels 获取图像信息
public SkiaSharp.SKPixmap PeekPixels ();
public bool PeekPixels (SkiaSharp.SKPixmap pixmap);
提供对 SKBitmap 内部像素数据的直接访问,而不需要复制数据。这在需要高效地读取或修改像素数据时非常有用
意义
- 性能优化:通过避免数据复制,
PeekPixels
可以提高性能,尤其是在处理大位图或频繁访问像素数据的情况下。 - 直接操作像素:允许开发者直接读取和操作位图的像素数据,从而实现一些低级别的图像处理操作,比如图像滤镜、特效等。
- 内存效率:减少内存占用,因为无需创建像素数据的副本。
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
if (skBmp == null) skBmp = SKBitmap.Decode(@"Images\AIWoman.png");
var sw=Stopwatch.StartNew();
var pixmap = new SKPixmap();
if (skBmp.PeekPixels(pixmap))
{
int width = pixmap.Width;
int height = pixmap.Height;
IntPtr pixels = pixmap.GetPixels();
// Example: Invert colors
unsafe
{
byte* ptr = (byte*)pixels;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int index = (i * width + j) * 4;
ptr[index] = (byte)(255 - ptr[index]); // R
ptr[index + 1] = (byte)(255 - ptr[index + 1]); // G
ptr[index + 2] = (byte)(255 - ptr[index + 2]); // B
}
}
}
}
sw.Stop();
using (var paint = new SKPaint())
{
paint.FilterQuality = SKFilterQuality.High;
canvas.DrawBitmap(skBmp, new SKRect(20, 20, 420, 420), paint);
paint.TextSize = 24;
canvas.DrawText($"Invert {pixmap.Width}x{pixmap.Height} elapsed time:{sw.ElapsedMilliseconds}ms", 20, 450, paint);
}
使用PeekPixels使用图像信息,并反转每个像素。
Reset 重置
public void Reset ();
将位图置为宽高都为0。释放资源、清空内容。
Resize 缩放
public SkiaSharp.SKBitmap Resize (SkiaSharp.SKImageInfo info, SkiaSharp.SKFilterQuality quality);
public SkiaSharp.SKBitmap Resize (SkiaSharp.SKSizeI size, SkiaSharp.SKFilterQuality quality);
缩放为指定尺寸和质量的图像。
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
if (skBmp == null) skBmp = SKBitmap.Decode(@"Images\AIWoman.png");
var resizeBmp = skBmp.Resize(new SKSizeI(400, 400), SKFilterQuality.High);
var sw = Stopwatch.StartNew();
if (resizeBmp != null)
{
using (var paint = new SKPaint())
{
paint.FilterQuality = SKFilterQuality.High;
canvas.DrawBitmap(resizeBmp, 20, 20, paint);
paint.TextSize = 24;
sw.Stop();
canvas.DrawText($"Size: {resizeBmp.Width}x{resizeBmp.Height} Elapsed time:{sw.ElapsedMilliseconds}ms", 20, 450, paint);
}
resizeBmp.Dispose();
}
sw.Restart();
using (var paint = new SKPaint())
{
paint.FilterQuality = SKFilterQuality.High;
canvas.DrawBitmap(skBmp, new SKRect(440, 20, 840, 420), paint);
paint.TextSize = 24;
sw.Stop();
sw.Stop();
canvas.DrawText($"Elapsed time:{sw.ElapsedMilliseconds}ms", 420, 450, paint);
}
缩放后绘制,与直接绘制为指定尺寸的图像,其性能不一样。
ScalePixels 缩放
public bool ScalePixels (SkiaSharp.SKPixmap destination, SkiaSharp.SKFilterQuality quality);
public bool ScalePixels (SkiaSharp.SKBitmap destination, SkiaSharp.SKFilterQuality quality);
将图像缩放结果保存到已创建的SKBitmap对象。
SetPixel/SetPixels 设置像素
public void SetPixel (int x, int y, SkiaSharp.SKColor color);
public void SetPixels (IntPtr pixels);
设置指定像素的颜色。
设置图像指定的像素内存地址。
ToShader 转为着色器
public SkiaSharp.SKShader ToShader ();
public SkiaSharp.SKShader ToShader (SkiaSharp.SKShaderTileMode tmx, SkiaSharp.SKShaderTileMode tmy);
public SkiaSharp.SKShader ToShader (SkiaSharp.SKShaderTileMode tmx, SkiaSharp.SKShaderTileMode tmy, SkiaSharp.SKMatrix localMatrix);
将位图 (SKBitmap) 转换为一个着色器 (SKShader),从而可以在绘制操作中使用该位图作为填充图案或纹理。通过这种方式,可以实现复杂的图形效果,例如图像填充、纹理映射等。
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
if (skBmp == null) skBmp = SKBitmap.Decode(@"Images\wall.png");
// 定义TileMode和Transform
var tileMode = SKShaderTileMode.Repeat;
var transform = SKMatrix.CreateScale(0.5f, 0.5f);
// 将SKBitmap转换为SKShader
using (SKShader shader = skBmp.ToShader(tileMode, tileMode, transform))
{
// 创建一个画笔,并设置其着色器为bitmap的着色器
using (SKPaint paint = new SKPaint())
{
paint.Shader = shader;
// 使用这个画笔来绘制一个矩形
SKRect rect = new SKRect(0, 0, info.Width,info.Height);
canvas.DrawRect(rect, paint);
}
}
SKBitmap转着色器,填充画布。
TryAllocPixels 尝试分配内存
public bool TryAllocPixels (SkiaSharp.SKImageInfo info);
public bool TryAllocPixels (SkiaSharp.SKImageInfo info, SkiaSharp.SKBitmapAllocFlags flags);
public bool TryAllocPixels (SkiaSharp.SKImageInfo info, int rowBytes);
尝试为 SKBitmap 对象分配像素数据的存储空间。成功调用后,SKBitmap 对象将有足够的内存来存储像素数据,可以用于绘制和图像处理操作。