前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >dotnet C# 使用 FreeType 读取和绘制字体

dotnet C# 使用 FreeType 读取和绘制字体

作者头像
林德熙
修改于 2024-04-25 01:11:49
修改于 2024-04-25 01:11:49
61500
代码可运行
举报
文章被收录于专栏:林德熙的博客林德熙的博客
运行总次数:0
代码可运行

本文将和大家介绍在 C# 里面简单使用 SharpFont 对 FreeType 的封装,读取 ttf 等字体文件信息,绘制出某个文字到图片文件

由于本文使用的 SharpFont 库已经很久没有维护了,本文的例子里面使用的 .NET 框架就退回到 .NET Framework 4.7.2 版本。我大概看了代码,预计 dotnet 6 等版本还是能够兼容的,只是为了方便我写例子代码,减少遇到一些奇怪的问题,本文的例子就采用比较旧的框架

开始之前先感谢 Robert Rouhani 大佬开源的 https://github.com/Robmaister/SharpFont 项目,尽管这个项目已经很久没有维护了

按照 .NET 的惯例,先通过 NuGet 安装库,我通过编辑 csproj 文件快速进行安装,编辑之后的 csproj 项目文件的代码如下

代码语言:csharp
AI代码解释
复制
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net472</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <LangVersion>latest</LangVersion>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="SharpFont" Version="4.0.1" />
  </ItemGroup>
</Project>

先通过 SetDllDirectory 按照 x64 或 x86 方式加载库,代码如下,以下这部分感觉是基础库没有封装好的部分

代码语言:csharp
AI代码解释
复制
        public static void Main(string[] args)
        {
            var folderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            var nugetFolder = Path.Combine(folderPath, @"..\.nuget\packages\sharpfont.dependencies");
            // 如果自己的 nuget 没有设置为其他路径的话
            var sharpFontDependenciesNuGetFolder = Directory.EnumerateDirectories(nugetFolder).First();

            if (Environment.Is64BitProcess)
            {
                var libraryFolder = Path.Combine(sharpFontDependenciesNuGetFolder, @"bin\msvc12\x64\");
                SetDllDirectory(libraryFolder);
            }
            else
            {
                var libraryFolder = Path.Combine(sharpFontDependenciesNuGetFolder, @"bin\msvc12\x86\");
                SetDllDirectory(libraryFolder);
            }

        }

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool SetDllDirectory(string path);

以上代码我是去找 NuGet 文件夹里面的依赖包里面的文件

完成以上步骤之后,即可创建出 Face 对象。如以下代码随意给一个字体文件进行测试

代码语言:csharp
AI代码解释
复制
            var library = new Library();
            var face = new Face(library, @"C:\windows\fonts\simfang.ttf");

接下来的代码将演示如何获取某个字符在字体里面的信息,以及将这个字体用这个字体渲染到本地图片文件

获取字符在字体里面的信息,需要先获取到字符在字体里面的索引,代码如下

代码语言:csharp
AI代码解释
复制
            uint glyphIndex = face.GetCharIndex('林');

以上代码就可以获取到 字在字体文件里面的索引

接下来为了将字体加载到 slot 里面,需要先设置一点必要的初始化参数

代码语言:csharp
AI代码解释
复制
            // 设置字体大小,修复 SharpFont.FreeTypeException:“FreeType error: Invalid size handle.”
            face.SetCharSize(26,0,96,0);

接着将字体加载到 slot 里面,用于后续获取 Glyph 属性,获取信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
            // 加载 slot 用于后续渲染
            face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);

完成以上步骤即可使用以下代码,获取到字符的信息

代码语言:csharp
AI代码解释
复制
            float advanceX = (float) face.Glyph.Advance.X; // same as the advance in metrics
            float bearingX = (float) face.Glyph.Metrics.HorizontalBearingX;
            float width = face.Glyph.Metrics.Width.ToSingle();
            float glyphTop = (float) face.Glyph.Metrics.HorizontalBearingY;
            float glyphBottom = (float) (face.Glyph.Metrics.Height - face.Glyph.Metrics.HorizontalBearingY);

以上的各个变量就是对于传入的字符的信息

将字体渲染到图片需要借助 GDI 部分的辅助,先调用 RenderGlyph 方法,再通过 ToGdipBitmap 转换为 System.Drawing.Bitmap 对象,用于保存到本地文件

代码语言:csharp
AI代码解释
复制
            face.Glyph.RenderGlyph(RenderMode.Normal);

            face.Glyph.Bitmap.ToGdipBitmap().Save("1.png");

以上的代码我都放在一个 Main 方法里面,代码如下

代码语言:csharp
AI代码解释
复制
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using SharpFont;

namespace ChewukeriLudikanal
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            var folderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            var nugetFolder = Path.Combine(folderPath, @"..\.nuget\packages\sharpfont.dependencies");
            // 如果自己的 nuget 没有设置为其他路径的话
            var sharpFontDependenciesNuGetFolder = Directory.EnumerateDirectories(nugetFolder).First();

            if (Environment.Is64BitProcess)
            {
                var libraryFolder = Path.Combine(sharpFontDependenciesNuGetFolder, @"bin\msvc12\x64\");
                SetDllDirectory(libraryFolder);
            }
            else
            {
                var libraryFolder = Path.Combine(sharpFontDependenciesNuGetFolder, @"bin\msvc12\x86\");
                SetDllDirectory(libraryFolder);
            }

            var library = new Library();
            var face = new Face(library, @"C:\windows\fonts\simfang.ttf");

            uint glyphIndex = face.GetCharIndex('林');

            // 设置字体大小,修复 SharpFont.FreeTypeException:“FreeType error: Invalid size handle.”
            face.SetCharSize(26,0,96,0);

            // 加载 slot 用于后续渲染
            face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);

            // 获取字体信息
            float advanceX = (float) face.Glyph.Advance.X; // same as the advance in metrics
            float bearingX = (float) face.Glyph.Metrics.HorizontalBearingX;
            float width = face.Glyph.Metrics.Width.ToSingle();
            float glyphTop = (float) face.Glyph.Metrics.HorizontalBearingY;
            float glyphBottom = (float) (face.Glyph.Metrics.Height - face.Glyph.Metrics.HorizontalBearingY);

            // 尝试获取字间距
            //kern = (float) face.GetKerning(glyphIndex, face.GetCharIndex(cNext), KerningMode.Default).X;
            face.Glyph.RenderGlyph(RenderMode.Normal);

            face.Glyph.Bitmap.ToGdipBitmap().Save("1.png");
        }

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool SetDllDirectory(string path);
    }
}

尝试运行代码,可以看到运行之后输出了 1.png 文件,用图片查看器打开可以看到里面绘制出了字符

本文代码放在 githubgitee 上,可以使用如下命令行拉取代码

先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

代码语言:bash
AI代码解释
复制
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin df6a50e5af79104064e91aca92f72d331fac7161

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码,将 gitee 源换成 github 源进行拉取代码

代码语言:bash
AI代码解释
复制
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin df6a50e5af79104064e91aca92f72d331fac7161

获取代码之后,进入 ChewukeriLudikanal 文件夹,即可获取到源代码

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
dotnet 如何从 Gtk 3 的窗口到对应的 X11 窗口
本文将告诉大家如何在 Gtk3 的 Gtk.Window 或 Gdk.Window 里面获取到对应的 X11 窗口 XID 号
林德熙
2024/05/16
2030
dotnet 如何从 Gtk 3 的窗口到对应的 X11 窗口
【批量图片区域识别改名】有没有可以自动批量识别jpg图片上的区域文字,并直接提取文字命名的软件么? 没有我们教你基于WPF和腾讯api的方案做一个
在很多实际工作场景中,我们可能会遇到大量的图片文件,这些图片中包含特定区域的文字信息,比如发票图片上的发票号码、合同图片上的合同编号等。手动识别并为图片命名效率极低且容易出错。使用自动批量识别 JPG 图片上的区域文字,并直接提取文字为图片命名的软件,可以大大提高工作效率,减少人工操作带来的错误。
不负众望
2025/02/24
1480
【批量图片区域识别改名】有没有可以自动批量识别jpg图片上的区域文字,并直接提取文字命名的软件么? 没有我们教你基于WPF和腾讯api的方案做一个
【硬核】韦东山:使用freetype显示一行文字
6.6 使用freetype显示一行文字 使用GIT下载所有源码后,本节源码位于如下目录: 01_all_series_quickstart 04_嵌入式Linux应用开发基础知识\source\10_freetype 04_show_line\show_line.c
韦东山
2020/09/30
2K0
C#如何加载嵌入到资源的非托管dll
我们总会遇到需要加载非Win32的非托管dll,这里推荐一种方式就是将那些非win32的非托管dll嵌入资源的方式,在入口解压并且加载的方式,我先来看看如何实现吧,首先我们准备好demo,新增控制台项目如下:
ryzenWzd
2021/05/17
1.1K0
C#如何加载嵌入到资源的非托管dll
dotnet WinUI3 Win2D 翻转图片
本文将告诉大家如何在 WinUI3 里面使用 Win2D 进行图片的翻转,本文的方法也适用于 UWP 框架
林德熙
2024/07/08
1610
dotnet OpenXML WPF 解析实现 PPT 文本描边效果
本文是使用 WPF 做个 PowerPoint 系列的博客,本文来告诉大家如何解析 PPT 里面的文本描边效果,在 WPF 应用中绘制出来,实现像素级相同
林德熙
2021/12/18
1K0
dotnet OpenXML WPF 解析实现 PPT 文本描边效果
dotnet OpenXML 读取 PPT 内嵌 xlsx 格式 Excel 表格的信息
在 Office 中,可以在 PPT 里面插入表格,插入表格有好多不同的方法,对应 OpenXML 文档存储的更多不同的方式。本文来介绍如何读取 PPT 内嵌 xlsx 格式的表格的方法
林德熙
2021/11/15
1.1K0
Roslyn 分析器 读取 csproj 项目文件的 AdditionalFiles Item 的 Metadata 配置
定义在 ItemGroup 里面的各个引用文件的 Item 可带上自定义的 Metadata 内容,这部分内容需要转换到 AdditionalFiles 的 Metadata 上才能被分析器所获取
林德熙
2024/10/12
1260
dotnet 使用 Refasmer 从现有的 DLL 里面导出公开的成员组装出新的仅作为引用用途的程序集
本文告诉大家 Resharper 家(JetBrains)开源的 Refasmer 工具,这个工具的功能就是从现有的 DLL 或 EXE 程序集里面,将所有的公开成员导出,重新打出新的 DLL 或 EXE 程序集。此时打出的新的程序集里面的方法都不包含实现,而是只有定义,这样的程序集被成为仅作为引用用途的程序集,也就是 Reference assemblies 的意思,这也就是 Refasmer 命名来源
林德熙
2021/12/23
6230
WPF 通过 RawInput 获取触摸消息
触摸在 Windows 下属于比较特殊的输入,不同于键盘和鼠标,键盘和鼠标可以通过全局 Hook 的方式获取到鼠标和键盘的输入消息。而触摸则没有直接的 Hook 的方法。如果期望自己的应用,可以在没有作为前台获取焦点的应用时,可以抓取到全局的触摸消息,抓取到其他应用程序的触摸输入,那么可以尝试使用 RawInput 的方式。通过 RawInput 的方式,可以让一个没有任何激活的、触摸直接命中的窗口的应用程序接收到全局的所有触摸消息
林德熙
2023/04/07
9081
C# 程序集数量对软件启动性能的影响
本文通过很多的数据测试分析在一个项目引用很多个外部项目和将外部项目的类合并到一个项目之间的启动性能的不同。 通过分析知道了如果一个项目引用了很多项目,而且在启动过程会全部调用这些项目,这时的软件性能会比将这些项目的代码合并到一个项目的慢很多 本文的数据为 预编译框架,开发高性能应用 - 课程 - 微软技术暨生态大会 2018 - walterlv 提供
林德熙
2019/03/13
6640
C# 程序集数量对软件启动性能的影响
38.opengl-字体渲染
早期的文本渲染,是将需要的字符集放到一个大纹理中,这个纹理称为“位图字体”,渲染某个字符时,通过查找坐标,找到该字符对应的区域并渲染出来,再启动混合,让字符纹理的背景保持透明,非常容易理解。
公号sumsmile
2020/10/10
1.8K0
38.opengl-字体渲染
dotnet C# 使用 SHFileOperation 调用 Win32 的文件复制对话框
本文将和大家介绍如何在 dotnet C# 里面使用 SHFileOperation 调用 Windows 自带的文件复制对话框进行文件复制
林德熙
2024/08/10
1130
dotnet C# 使用 SHFileOperation 调用 Win32 的文件复制对话框
C# 性能分析 反射 VS 配置文件 VS 预编译
本文分析在 C# 中使用反射和配置文件和预编译做注入的性能,本文的数据是为预编译框架,开发高性能应用 - 课程 - 微软技术暨生态大会 2018 - walterlv提供
林德熙
2019/03/13
6870
C# 性能分析 反射 VS 配置文件 VS 预编译
dotnet C# 使用 Win32 函数获取用户下载文件夹的路径的方法
大家都知道,在 dotnet 里面的可以使用 Environment.GetFolderPath 方法配合 Environment.SpecialFolder 枚举列出当前运行环境下的一些特殊文件夹。然而 SpecialFolder 枚举不包含对 Download 下载文件夹的枚举值,如咱需要获取用户当前的下载文件夹,需要使用 Win32 方法来辅助获取
林德熙
2024/04/13
2170
freetype的交叉编译及在嵌入式linux上的简单使用及改变字体背景和颜色
FreeType库是一个完全免费(开源)的、高质量的且可移植的字体引擎,它提供统一的接口来访问多种字体格式文件,包括TrueType, OpenType, Type1, CID, CFF, Windows FON/FNT, X11 PCF等。它支持单色位图、反走样位图的渲染。FreeType库是高度模块化的程序库,虽然它是使用ANSI C开发,但是采用面向对象的思想,因此,FreeType的用户可以灵活地对它进行裁剪。关于freetype的详细信息可以参考freetype的官方网站:https://www.freetype.org/来获取更多相关的信息。
杨永贞
2020/12/16
5.2K0
freetype的交叉编译及在嵌入式linux上的简单使用及改变字体背景和颜色
dotnet 启动进程传入不存在的文件夹作为工作目录行为变更
本文记录在 dotnet 下,启动进程,传入不存在的文件夹作为进程的工作目录,分别在 .NET Framework 和 .NET Core 的行为
林德熙
2022/03/15
9230
dotnet C# 创建 X11 应用时设置窗口背景颜色
在 dotnet C# 设置 X11 应用窗口背景透明 的基础上,可以通过创建 XColor 结构体,将 XColor 赋值给到 XSetWindowAttributes 的 background_pixel 进行设置窗口的初始化背景颜色
林德熙
2024/06/01
1290
如何通过SK集成chatGPT实现DotNet项目工程化?
当前文档对应src/assistant/Chat.SemanticServer项目
用户10786849
2023/10/22
3050
如何通过SK集成chatGPT实现DotNet项目工程化?
dotnet C# 简单的追加文件夹到 ZipArchive 压缩文件的方法
本文将告诉大家一个在 ZipArchive 里追加文件夹,以及添加过滤文件处理的压缩文件辅助方法
林德熙
2024/04/27
3050
推荐阅读
相关推荐
dotnet 如何从 Gtk 3 的窗口到对应的 X11 窗口
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档