Skip to content

使用 SkiaSharp 在 C# 中生成图像

Published: at 12:00 AM

使用 SkiaSharp 在 C# 中生成图像

摘要

在本文中,我们将学习如何使用 SkiaSharp 库在 C# 中生成图像,包括图像创建和修改的示例。


在本文中,我们将学习如何使用 SkiaSharp 在 C# 中生成图像。

要下载本文的源代码,您可以访问我们的 GitHub 仓库

让我们开始吧。

什么是 SkiaSharp?

SkiaSharp 库是基于 Google 的 Skia 图形库的、适用于 .NET 平台的跨平台 2D 图形 API,它是一个用于绘制文本、几何图形和图像的全面库。这个库是 Google 产品如 Google Chrome、ChromeOS、Android 和 Flutter 中使用的图形引擎。

在本文中,我们将探索使用 SkiaSharp 创建一个空白图像,然后在创建的图像中间绘制一个正方形。

首先,让我们在终端上导航到项目目录,以便导入 NuGet 包:

dotnet add package SkiaSharp

创建图像

接下来,让我们创建一个 ImageService 静态类,在其中定义一些辅助方法,从创建一个空白图像开始:

public static SKBitmap CreateBlankImage(int width, int height)
{
    var bitmap = new SKBitmap(width, height);
    using var canvas = new SKCanvas(bitmap);
    canvas.Clear(SKColors.White);
    return bitmap;
}

这里我们看到了我们的 CreateBlankImage() 静态方法的定义,它接受 widthheight 作为参数,并返回类型为 SKBitmapbitmap,在 SkiaSharp 中代表一个图像。

我们开始时创建一个给定 widthheightSKBitmap 对象。接下来,我们使用我们的 SKBitmap 初始化一个新的 SKCanvas 对象。通过这个操作,我们将画布与位图连接起来。SKCanvas 类在 SkiaSharp 中表示画布或绘图面。它提供用于绘制图形、文本和图像的方法。

当我们最初创建一个位图时,其像素数据由未定义的随机值组成。通过使用 SKCanvas() 构造函数将位图附加到一个画布上,我们创建了一种操纵图像像素数据的手段。没有画布,位图将保持未初始化的随机值。

注意 SKCanvas 对象是可释放的,因此添加了 using 声明以确保适当的清理。

接下来,我们使用 SKCanvas.Clear(SKColor) 方法清除整个画布。Clear() 方法将画布中的所有像素设置为单一颜色,在我们的案例中是 SKColors.White。如果我们调用 Clear() 的无参数重载,所有像素将被设置为 SKColor.Empty (#00000000)。

操作图像

现在,让我们创建一个方法在我们的图像中心绘制一个正方形:

public static void DrawSquareOnImage(SKBitmap bitmap, int squareSize, int startX, int startY)
{
    if (squareSize <= 0 || startX <= 0 || startY <= 0)
    {
        throw new ArgumentException("正方形的大小和坐标必须大于零。");
    }
    using var canvas = new SKCanvas(bitmap);
    using var paint = new SKPaint();
    paint.Color = SKColors.Red;
    var square = new SKRect(startX, startY, startX + squareSize, startY + squareSize);
    canvas.DrawRect(square, paint);
}

这里我们定义了我们的 DrawSquareOnImage() 方法,它将在提供的图像上绘制一个正方形。它接受四个参数,即我们将要绘制的 SKBitmap 对象、squareSizestartXstartYsquareSize 代表我们将要绘制的正方形的大小,而 startXstartY 代表正方形起始点的 X 和 Y 坐标。

首先,我们验证所有的 int 参数值都大于零。

接下来,我们为在位图上绘制而创建一个新的 SKCanvas 对象。之后,我们实例化一个新的 SKPaint 对象并将其 Color 设置为 SKColors.Red。我们使用 SKPaint 来定义图形、几何形状和位图的样式和颜色信息。

接下来,我们创建了一个 SKRect 实例,这是一个包含矩形四个坐标的结构,在我们的案例中是一个正方形。然后最后,我们使用 DrawRect() 方法在画布上绘制正方形,该方法接受一个 SKRect 参数(square)和一个 SKPaintpaint)参数。

保存图像

现在,让我们创建一个方法来保存图像:

public static void SaveImage(SKBitmap bitmap, string outputPath)
{
    using var stream = new FileStream(outputPath, FileMode.Create, FileAccess.Write);
    using var image = SKImage.FromBitmap(bitmap);
    using var encodedImage = image.Encode();
    encodedImage.SaveTo(stream);
}

这里我们定义了我们的 SaveImage() 静态方法,它接受两个参数:bitmapoutputPath

我们首先实例化一个 FileStream 对象用于文件创建,将 FileMode 设置为 FileMode.Create 来创建或覆盖一个文件,如果它已经存在,并且将 FileAccess 设置为 FileAccess.Write

接下来,我们将我们的位图转换为 SKImage,然后调用无参数的 Encode() 方法,默认将我们的 SKImage 编码为 PNG 格式。然后我们最终将其保存到 FileStream

using 声明确保在使用完每个可释放对象后调用 Dispose() 方法,以确保适当的资源管理。

生成样本图像

现在,让我们将我们之前创建的方法带到我们的 Program 类中,并创建一个新图像:

string outputPath = @"outputImage.png";
int imageWidth = 400;
int imageHeight = 300;
int squareSize = 120;
int startX = (imageWidth - squareSize) / 2;
int startY = (imageHeight - squareSize) / 2;
var bitmap = ImageService.CreateBlankImage(imageWidth, imageHeight);
ImageService.DrawSquareOnImage(bitmap, squareSize, startX, startY);
ImageService.SaveImage(bitmap, outputPath);
Console.WriteLine("图像成功生成并保存。");

我们指定一个目录路径,我们生成的图像 outputImage.png 将被保存在这个目录。我们想要的目录是包含我们的 .exe 文件的文件夹,即我们的 “net8.0” 文件夹。

我们将 imageWidthimageHeightsquareSize 设置为分别为 400px、300px 和 120px。

接下来,我们通过提供 imageWidthsquareSize 来计算我们的正方形相对于 x 轴的起始点。同样,我们提供 imageHeightsquareSize 来计算我们正方形的 y 轴起始点。

之后,我们从我们的 ImageService 类中调用 CreateBlankImage() 方法,提供 imageWidthimageHeight,来创建我们的 bitmap

有了我们的图像之后,我们然后调用我们的 DrawSquareOnImage() 方法,提供我们的 bitmap 和我们之前计算的值:squareSizestartXstartY。通过这种方式,正方形被绘制在我们的 bitmap

最后,我们将我们修改后的 bitmap 保存到我们之前定义的 outputPath,控制台上打印出确认消息。

让我们测试一下:

图像成功生成并保存。

如预期,我们得到了成功消息。现在让我们检查我们的图像:

使用 SkiaSharp 库生成的图像

结论

在本文中,我们通过操作一些示例图像,查看了如何使用 SkiaSharp 库在 C# 中生成和操作图像。