SkiaSharp画的验证码在Linux下无法正常显示

  1. SkiaSharp是Google的Skia图形库的.NET封装版,可用于跨移动、服务器和桌面平台绘制 2D 图形。SkiaSharp 可与 OpenGL 一起用于硬件加速渲染。SkiaSharp 最初由 Mono 开发,但现在由 Microsoft 维护,并根据MIT License提供。

  2. 使用SkiaSharp生成验证码图片示例代码

using SkiaSharp;
using System.Text;

namespace TestApi;

public static class VerificationCodeHelper
{
    public static string GetRandomCode(int length)
    {
        StringBuilder code = new();
        string text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
        Random random = new();
        for (int i = 0; i < length; i++)
        {
            code.Append(text[random.Next(0, text.Length)]);
        }
        return code.ToString();
    }

    public static byte[] GetVerificationCode(string text)
    {
        int width = 128;
        int height = 45;
        Random random = new();

        using SKBitmap image = new(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
        using SKCanvas canvas = new(image);
        canvas.DrawColor(SKColors.White);

        // 画干扰线
        // 干扰线占图片面积的比例
        decimal distractorLineRate = 0.0005M;
        for (int i = 0; i < (width * height * distractorLineRate); i++)
        {
            using SKPaint _drawStyle = new();
            _drawStyle.Color = new(Convert.ToUInt32(random.Next(int.MaxValue)));
            canvas.DrawLine(random.Next(0, width), random.Next(0, height), random.Next(0, width), random.Next(0, height), _drawStyle);
        }

        // 画文本
        using SKPaint drawStyle = new();
        drawStyle.Color = SKColors.Red;
        drawStyle.TextSize = height;
        drawStyle.IsAntialias = true; // 抗锯齿

        // 文本居中显示
        float textWidth = drawStyle.MeasureText(text);
        float x = (width - textWidth) / 2;
        float y = (height + drawStyle.TextSize) / 2; // 调整Y轴位置以居中

        // 绘制每个字符
        foreach (char c in text)
        {
            string character = c.ToString();
            float charWidth = drawStyle.MeasureText(character);
            float charRotation = random.Next(-15, 15); // 随机旋转角度

            canvas.Save();
            canvas.RotateDegrees(charRotation, x + charWidth / 2, y - drawStyle.TextSize / 2);
            canvas.DrawText(character, x, y, drawStyle);
            canvas.Restore();

            x += charWidth;
        }

        // 绘制噪点
        for (int i = 0; i < (width * height * 0.6); i++)
        {
            image.SetPixel(random.Next(0, width), random.Next(0, height), new SKColor(Convert.ToUInt32(random.Next(int.MaxValue))));
        }

        using var img = SKImage.FromBitmap(image);
        using SKData p = img.Encode(SKEncodedImageFormat.Png, 100);
        return p.ToArray();
    }
}
  1. 调用示例代码
app.MapGet("/testVerificationCode", (HttpContext httpContext) =>
{
    var randomText = VerificationCodeHelper.GetRandomCode(4);
    return Results.File(VerificationCodeHelper.GetVerificationCode(randomText), "image/png");
})
.WithName("TestVerificationCode")
.WithOpenApi();
  1. Windows下运行效果展示
    image

  2. Linux下运行效果展示
    image

检查日志得到,缺少了libSkiaSharp或任意它的分装库:
image

  1. 换源并安装libgdiplus(使用的镜像是官方镜像,基于debian12):
#备份旧源文件
cp -rf /etc/apt/sources.list.d /etc/apt/sources.list.d.bak
#删除旧源文件
rm -rf /etc/apt/sources.list.d/*
#创建源文件指向华为云源
cat <<'EOF'> /etc/apt/sources.list.d/huawei-cloud.list
deb https://mirrors.huaweicloud.com/debian/ bookworm main contrib non-free
deb https://mirrors.huaweicloud.com/debian/ bookworm-updates main contrib non-free
deb https://mirrors.huaweicloud.com/debian/ bookworm-backports main contrib non-free
deb https://mirrors.huaweicloud.com/debian-security/ bookworm-security main contrib non-free
EOF

cat <<'EOF'> fix_skiasharp_broke.sh
#!/bin/bash

# 更新包依赖树,确保最新
apt-get update -y

# 安装 libgdiplus 库,这是 System.Drawing.Common 在 Linux 上的依赖
apt-get install -y libgdiplus

# 清理 apt 缓存,减少镜像大小
apt-get clean

# 检查是否存在 /usr/lib/gdiplus.dll 文件,如果不存在,则创建一个指向 libgdiplus.so 的符号链接
# 这是为了兼容某些依赖 gdiplus.dll 的应用
if [ ! -f /usr/lib/gdiplus.dll ]; then
    ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll
fi
EOF

sh fix_skiasharp_broke.sh
  1. 重启容器并检查运行效果
    image

  2. End

posted @ 2024-07-22 19:05  Ar4te  阅读(121)  评论(0编辑  收藏  举报