【SkiaSharp绘图04】SKPaint详解(二)FakeBoldText/FilterQuality/FontMetrics/FontSpacing/ImageFilter

SKPaint属性

FakeBoldText 仿粗体

public bool FakeBoldText { get; set; }

获取或设置,是否启用了仿粗体文本。

var canvas = e.Surface.Canvas;
var into = e.Info;
canvas.Clear(SKColors.White);

using (var paint = new SKPaint())
{
    paint.TextSize = 18;
    paint.Typeface = SKTypeface.FromFamilyName("宋体");

    canvas.DrawText($"FakeBoldText值={paint.FakeBoldText}", 20, 20, paint);

    paint.FakeBoldText = !paint.FakeBoldText;
    canvas.DrawText($"FakeBoldText值={paint.FakeBoldText}", 20, 40, paint);
}

测试FakeBoldText不同值时的效果。
FakeBoldText

FilterQuality 图像质量

public SkiaSharp.SKFilterQuality FilterQuality { get; set; }

获取或设置当前SKPaint的图像质量(影响缩放、旋转图像的质量(和性能))。
SKFilterQuality 枚举类型表示图像的过滤质量,用于控制当图像被缩放或者旋转时如何进行平滑处理。这个枚举类型定义了以下几个选项:

  1. None: 表示没有过滤,图像在缩放或旋转时可能会出现锯齿或失真,但处理速度较快。

  2. Low: 表示低质量的过滤,适用于快速处理,但图像质量略有提升。

  3. Medium: 表示中等质量的过滤,提供了一定程度的平滑处理,适用于大多数一般情况下的图像处理。

  4. High: 表示高质量的过滤,用于要求较高的图像平滑处理,如需要显示高质量的缩放或旋转图像。

通常来说,选择更高的过滤质量会导致更平滑和更清晰的图像,但可能会增加处理的时间和资源消耗。
绘图函数

static SKBitmap qualityImg = null;
/// <summary>
/// 绘制图像
/// </summary>
/// <param name="canvas"></param>
/// <param name="x">图像左上角x</param>
/// <param name="y">图像左上角y</param>
/// <param name="tipText">提示文字</param>
/// <param name="paint"></param>
/// <param name="width">图像宽</param>
/// <param name="height">图像高</param>
private void DrawBitmap(SKCanvas canvas, float x, float y, string tipText, SKPaint paint,float width=380, float height = 380)
{
    if (qualityImg == null)
    {
        qualityImg = SKBitmap.Decode(@"Images\AIWoman.png");
    }
    canvas.DrawBitmap(qualityImg,new SKRect(x, y, x+width,y+ height),paint);
    canvas.DrawText(tipText, x, y - 10, paint);
}

枚举FilterQuality并设置后绘制图像

var canvas = e.Surface.Canvas;
var into = e.Info;
canvas.Clear(SKColors.White);

using (var paint = new SKPaint())
{
    var qualities = Enum.GetValues(typeof(SKFilterQuality)) as SKFilterQuality[];

    for (int i = 0; i < qualities.Length; i++)
    {
        paint.FilterQuality = qualities[i];
        DrawBitmap(canvas, (i % 2) * 400 + 20, (i / 2) * 400 + 20, $"{paint.FilterQuality}", paint);
    }
}

FilterQuality
从头发丝可以看出,不同质量的图像绘制效果有所区别。

FontMetrics 字体规格

public SkiaSharp.SKFontMetrics FontMetrics { get; }

获取字体规格。
定义一个函数,通过反射,可以列出SKFontMetrics 对象的所有属性。并根据字体的行距来控制行间距。

/// <summary>
/// 显示字体规格属性
/// </summary>
/// <param name="canvas"></param>
/// <param name="paint"></param>
/// <param name="x"></param>
/// <param name="y"></param>
private void ShowFontMetrics(SKCanvas canvas,SKPaint paint,float x,float y)
{
    var fontMetrics = paint.FontMetrics;
    var type = typeof(SKFontMetrics);

    var properties = type.GetProperties();
    canvas.DrawText($"{paint.Typeface.FamilyName}",x,y, paint);
    foreach (var property in properties)
    {
        y += paint.FontSpacing;
        var name = property.Name;
        var value = property.GetValue(fontMetrics);
        canvas.DrawText($"{name}:{value}", x, y, paint);                
    }
    canvas.DrawText($"FontSpacing:{paint.FontSpacing}",x,y+ paint.FontSpacing, paint);
}

通过设置“宋体”和“微软雅黑”,查看其字体规格属性的不同值。

var canvas = e.Surface.Canvas;
var into = e.Info;
canvas.Clear(SKColors.White);

using (var paint = new SKPaint())
{
    paint.Color = SKColors.Red;
    paint.TextSize = 18;
    paint.Typeface = SKTypeface.FromFamilyName("宋体");
    ShowFontMetrics(canvas, paint, 20,22);
    paint.TextSize = 20;
    paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");
    ShowFontMetrics(canvas, paint, 300, 22);
}

FontMetrics和FontSpacing

简要介绍几个重要的属性值的意义:

  1. Top

    • 表示字体基线(baseline)以上的最高点的坐标。对于大多数拉丁字母,这个值通常是负的,因为大多数字形的顶部在基线之上。
  2. Ascent

    • 表示字体的上升(ascent)值,即从基线到字体最高点的距离。正值表示从基线向上的距离,通常包括字符顶部的额外空间。
  3. Descent

    • 表示字体的下降(descent)值,即从基线向下到字体最低点的距离。正值表示从基线向下的距离,通常包括字符底部的额外空间。
  4. Bottom

    • 表示字体基线以下的最低点的坐标。这个值通常是负的,因为大多数字形的底部在基线以下。
  5. Leading

    • 表示字体的行间距(leading),即每行文字之间的额外空间。它是 ascent 和 descent 之间的间距。
  6. CapHeight

    • 表示大写字母的高度,即大写字母的顶部到基线的距离。这个值对于调整字体大小和行高很有用。
  7. XHeight

    • 表示小写字母的高度,即小写字母 x 的顶部到基线的距离。它通常用于调整字体大小和行高,以确保小写字母的清晰显示。

在控制文本的的布局、行高和间距时需要用到,这些值可以更好地控制文本的外观和布局,确保文字能准确对齐和显示。

FontSpacing 行距

public float FontSpacing { get; }

获取行距。表示从一行文本的基线到下一行文本基线的距离。
示例见上图。

HintingLevel 字体渲染提示级别

public SkiaSharp.SKPaintHinting HintingLevel { get; set; }//默认值为Normal

获取或设置字体渲染提示的级别。
各值的意义

  1. NoHinting (0): 这个选项表示不应用任何提示技术。文本将直接渲染,不考虑像素网格的对齐。这可能会导致文本在某些分辨率下看起来不够清晰。

  2. Slight (1): 这个选项提供轻微的提示级别。它将对文本进行一些基本的调整,以使其更好地适应像素网格,但不会进行过多的改变。这种级别的提示在需要快速渲染但也希望文本看起来稍微清晰一些的情况下很有用。

  3. Normal (2): 这是默认的提示级别。它提供了一个平衡的提示,旨在保持文本的可读性,同时确保它在不同的显示设备上看起来尽可能一致。这种级别的提示适合大多数情况。

  4. Full (3): 这个选项提供最全面的提示。它会尽可能地调整文本,以确保每个字形都完美地对齐到像素网格。这种级别的提示可能会导致渲染速度变慢,但可以提供最清晰的文本显示效果。值得注意的是,当渲染子像素字形时,Full 级别会与 Normal 级别相同。

var canvas = e.Surface.Canvas;
var into = e.Info;
canvas.Clear(SKColors.White);
var colors = new SKColor[] { SKColors.Black, SKColors.Red, SKColors.Green, SKColors.Blue };

using (var paint = new SKPaint())
{
    paint.Color = SKColors.Red;
    paint.TextSize = 48;
    paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");
    paint.IsAntialias = true;
    var hints = Enum.GetValues(typeof(SKPaintHinting)) as SKPaintHinting[];

    var offsetY = 80F;
    int i = 0;
    foreach(var hint in  hints)
    {
        paint.Color = colors[i];
        paint.HintingLevel = hint;
        canvas.DrawText($"测试HintingLevel:{hint}", 20, offsetY, paint);
        offsetY += paint.FontSpacing;
        i++;

    }
}

没看出有什么区别,默认值为Normal。
HintingLevel

ImageFilter获取或设置图像滤镜

public SkiaSharp.SKImageFilter ImageFilter { get; set; }

CreateAlphaThreshold 透明遮罩

public static SkiaSharp.SKImageFilter CreateAlphaThreshold (SkiaSharp.SKRectI region, float innerThreshold, float outerThreshold, SkiaSharp.SKImageFilter input = default);
public static SkiaSharp.SKImageFilter CreateAlphaThreshold (SkiaSharp.SKRegion region, float innerThreshold, float outerThreshold, SkiaSharp.SKImageFilter input = default);

创建一个带透明度的遮罩。
如果样本位于该区域内,则图像的 alpha 值将提升至阈值。如果它在该区域之外,则将 alpha 减小到阈值。该区域的 (0, 0) 点对应于源图像的左上角。

SKBitmap skBmp = null;
[System.ComponentModel.Description("SKPaint的CreateAlphaThreshold")]
public void OnPaintSurface04_05(object sender, SkiaSharp.Views.Desktop.SKPaintGLSurfaceEventArgs e)
{
    var canvas = e.Surface.Canvas;
    canvas.Clear(SKColors.White);
    
    if(skBmp==null)
    {
        skBmp = SKBitmap.Decode(@"Images\AIWoman.png");
    }

    // 创建透明度阈值图像滤镜
    var thresholdA = 0.1F;// 透明度阈值范围在 0.0(完全透明)到 1.0(完全不透明)之间
    var thresholdB = 0.7F;
    using (SKImageFilter alphaThresholdFilter1 = SKImageFilter.CreateAlphaThreshold(new SKRectI(100, 100, 300, 300), thresholdA, thresholdB))
    using (SKImageFilter alphaThresholdFilter2 = SKImageFilter.CreateAlphaThreshold(new SKRectI(500, 100, 700, 300), thresholdB, thresholdA))
    using (var paint = new SKPaint())
    {
        paint.Color = SKColors.Red;
        paint.TextSize = 12;
        paint.Typeface = SKTypeface.FromFamilyName("宋体");

        paint.FilterQuality = SKFilterQuality.High;
        paint.ImageFilter = alphaThresholdFilter1;
        canvas.DrawBitmap(skBmp, new SKRect(10, 10, 400, 400), paint);
        canvas.DrawText($"innerThreshold:{thresholdA},outerThreshold:{thresholdB}", 10, 420, paint);
        

        paint.ImageFilter = alphaThresholdFilter2;
        canvas.DrawBitmap(skBmp, new SKRect(410, 10, 800, 400), paint);
        canvas.DrawText($"innerThreshold:{thresholdB},outerThreshold:{thresholdA}", 410, 420, paint);
    }
}

第一张,外面的透明度为0.7F;第二张,外面的透明度为0.1F。
CreateAlphaThreshold

CreateArithmetic 算术

public static SkiaSharp.SKImageFilter CreateArithmetic (float k1, float k2, float k3, float k4, bool enforcePMColor, SkiaSharp.SKImageFilter background, SkiaSharp.SKImageFilter foreground = default, SkiaSharp.SKImageFilter.CropRect cropRect = default);

计算公式:output = clamp(K1 * src * dst + K2 * src + K3 * dst + K4)
SKImageFilter.CreateArithmetic 方法的主要作用是根据输入图像的颜色通道值和指定的算术运算参数,对图像进行算术合成,从而生成新的图像。其意义在于能够灵活地对图像进行复杂的颜色处理,广泛应用于图像合成、特效制作等领域。

CreateBlendMode混合

public static SkiaSharp.SKImageFilter CreateBlendMode (SkiaSharp.SKBlendMode mode, SkiaSharp.SKImageFilter background, SkiaSharp.SKImageFilter foreground = default, SkiaSharp.SKImageFilter.CropRect cropRect = default);

SKImageFilter.CreateBlendMode 的主要作用是根据指定的混合模式,将源图像和目标图像进行混合处理,生成新的图像。它提供了多种预定义的混合模式,可以实现各种复杂的图像效果,比如颜色叠加、色调调整、透明度合成等。

CreateBlur模糊

public static SkiaSharp.SKImageFilter CreateBlur (float sigmaX, float sigmaY, SkiaSharp.SKImageFilter input = default, SkiaSharp.SKImageFilter.CropRect cropRect = default);
public static SkiaSharp.SKImageFilter CreateBlur (float sigmaX, float sigmaY, SkiaSharp.SKShaderTileMode tileMode, SkiaSharp.SKImageFilter input = default, SkiaSharp.SKImageFilter.CropRect cropRect = default);

SKImageFilter.CreateBlur 是 SkiaSharp 中用于创建模糊滤镜的方法。模糊滤镜通过对图像进行模糊处理,能够实现柔化、虚化等效果,常用于图像处理、特效制作和图像增强等场景。

var canvas = e.Surface.Canvas;
canvas.Clear(SKColors.White);

if (skBmp == null)
{
    skBmp = SKBitmap.Decode(@"Images\AIWoman.png");
}

// 创建算术合成滤镜
float k1 = 0.5f, k2 = 0.5f, k3 = 0.5f, k4 = 0.0f;
using (SKImageFilter filter = SKImageFilter.CreateArithmetic(k1, k2, k3, k4, true, null, null))
using (SKImageFilter filter2 = SKImageFilter.CreateBlendMode(SKBlendMode.Multiply, null))
using (var paint = new SKPaint())
{
    paint.FilterQuality = SKFilterQuality.High;
    canvas.DrawBitmap(skBmp, new SKRect(10, 10, 400, 400), paint);//原图
    

    paint.ImageFilter = filter;
    canvas.DrawBitmap(skBmp, new SKRect(410, 10, 800, 400), paint);//CreateArithmetic滤镜

    paint.ImageFilter = filter2;
    canvas.DrawBitmap(skBmp, new SKRect(10, 410, 400, 800), paint);//CreateBlendMode滤镜

    // 创建模糊滤镜
    float sigmaX = 2F; // 横向模糊程度
    float sigmaY = 3F; // 纵向模糊程度
    using (var blurFilter = SKImageFilter.CreateBlur(sigmaX, sigmaY))
    {
        paint.ImageFilter = blurFilter;
        canvas.DrawBitmap(skBmp, new SKRect(410, 410, 800, 800), paint);//CreateBlur滤镜
    }

    paint.ImageFilter = null;
    paint.Color = SKColors.Red;
    paint.TextSize = 36;
    paint.Typeface = SKTypeface.FromFamilyName("宋体");
    canvas.DrawText($"原图", 20, 200, paint);
    canvas.DrawText($"CreateArithmetic", 420, 200, paint);
    canvas.DrawText($"CreateBlendMode", 20, 600, paint);
    canvas.DrawText($"CreateBlur", 420, 600, paint);
}

三种不同的图像滤镜创建方法示例。
图像滤镜

import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.File; import javax.imageio.ImageIO; public class TextToImage { public static void main(String[] args) { String text = "Hello, World!\n这是Java生成的图片。"; String fontName = "宋体"; int fontSize = 24; Color textColor = Color.BLACK; Color backgroundColor = Color.WHITE; int imageWidth = 400; int imageHeight = 200; String outputPath = "output.png"; // 生成图片 BufferedImage image = createTextImage(text, fontName, fontSize, textColor, backgroundColor, imageWidth, imageHeight); // 保存图片 saveImage(image, outputPath); System.out.println("图片已生成并保存到: " + outputPath); } /** * 根据文字生成图片 * * @param text 文字内容 * @param fontName 字体名称 * @param fontSize 字体大小 * @param textColor 文字颜色 * @param backgroundColor 背景颜色 * @param width 图片宽度 * @param height 图片高度 * @return 生成的图片 */ public static BufferedImage createTextImage(String text, String fontName, int fontSize, Color textColor, Color backgroundColor, int width, int height) { // 创建图片对象 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g2d = image.createGraphics(); // 设置背景颜色 g2d.setColor(backgroundColor); g2d.fillRect(0, 0, width, height); // 设置字体 Font font = new Font(fontName, Font.PLAIN, fontSize); g2d.setFont(font); g2d.setColor(textColor); // 开启抗锯齿 g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); // 计算文字位置 FontMetrics fontMetrics = g2d.getFontMetrics(); String[] lines = text.split("\n"); // 按换行符分割文字 int lineHeight = fontMet
最新发布
03-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图南科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值