フォントライブラリを使用したテキストレンダリング| .NET

概要

テキストを画像にレンダリングする機能を作成したい場合は、こちらの記事では、Aspose.font APIソリューションを使用してフォントライブラリでサポートされているフォームのフォントでそれを行う方法を教えます。ライブラリを使用すると、テキストを簡単に画像に変換したり、任意の画像にテキストを追加できます。

レンダリングテキスト

画像にテキストを描画するには、 RenderingUtils クラスの DrawText メソッドを使用します。この例では「Hello world」を Verdana で描画し、PNG ストリームを Text.png に保存します。

DataDir には TTF/verdana.ttf と TTF/LatoWeb-Regular.ttf を含むディレクトリを、OutputDir には既存の出力ディレクトリを指定します。使用する名前空間は Aspose.Font, Aspose.Font.Sources, Aspose.Font.Renderers, System, System.IO です。テストプロジェクトでは、BaseTests がこれらのディレクトリとライセンス設定を提供します。

 1// Render text to a PNG image
 2
 3string fontPath = Path.Combine(DataDir, "TTF", "verdana.ttf");
 4Font font = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(fontPath)));
 5string text = "Hello world";
 6string outFile = Path.Combine(OutputDir, "Text.png");
 7using (Stream image = RenderingUtils.DrawText(font, text, 18))
 8{
 9    image.Position = 0;
10    using FileStream output = File.Create(outFile);
11    image.CopyTo(output);
12}
Example-DrawText.cs hosted with ❤ by GitHub

実行結果:

Verdana で描画した Hello world

drawTextメソッドを使用すると、線間隔を設定し、自動ワードごとのテキストラップを実行できます。

以下のコードの例では、線間隔 linespacingtype.pixelsを指定し、10に設定し、画像の最大幅を450に設定しました。

指定された範囲(この場合は450)で正しく表示できないすべてのテキストは、新しいラインにラップされます。

この例では Verdana の「Hello world」を繰り返し、幅 450 ピクセルを超えるテキストを複数行に折り返します。結果は WrappedText.png に保存されます。

 1// Render wrapped text with pixel line spacing
 2
 3string fontPath = Path.Combine(DataDir, "TTF", "verdana.ttf");
 4Font font = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(fontPath)));
 5string text = "Hello world Hello world Hello world Hello world Hello world Hello world";
 6string outFile = Path.Combine(OutputDir, "WrappedText.png");
 7using (Stream image = RenderingUtils.DrawText(font, text, 22, RenderingUtils.LineSpacingType.Pixels, 10, 450))
 8{
 9    image.Position = 0;
10    using FileStream output = File.Create(outFile);
11    image.CopyTo(output);
12}

実行結果:

Verdana の Hello world の折り返し表示

DrawText() は PNG ストリームを返します。例ではストリームの位置を先頭に戻し、ファイルにコピーしてから両方のストリームを解放します。

drawText()メソッドの関数ファミリーは、標準テキストまたはマルチラインテキスト出力をカバーしています。ただし、場合によっては、テキストのカスタマイズされた出力が必要になる場合があります。たとえば、テキストを斜めに圧縮、伸ばし、回転させる場合、または他のものでテキストを回転させる場合です。この場合、ニーズに応じて出力をカスタマイズする必要があります。

カスタムテキストレンダリング

以下の例では、Windows 上の System.Drawing.Common を使用して、300 DPI、960 x 720 ピクセルのキャンバスにグリフの輪郭を描画します。前述の名前空間に加えて Aspose.Font.Glyphs, Aspose.Font.Rendering, Aspose.Font.RenderingPath, System.Drawing, System.Drawing.Drawing2D, System.Drawing.Imaging をインポートしてください。

Aspose.Font内で glyphsを描画するには、 glyphoutlinererderクラスのrenderglyph() `メソッドの1つを使用します。これらのオーバーロードされたメソッドはすべて、 iglyphrendererインターフェイスで宣言されています。

パラメーターとして、これらのメソッドにフォント、グリフィドまたはグリフインデックス、およびグリフ出力座標への参照を渡す必要があります。最後のパラメーターを転送するには、Aspose.Font transformationMatrixで表される特別なマトリックスが使用されます。 以下に、 transformationMatrixタイプのオブジェクトを使用する方法を示して、GLYPH出力座標をrenderglyph() `ファミリーの方法に渡します。

したがって、グリフを描くには、 glyphoutlinerenderタイプのオブジェクトを作成する必要があります。しかし、そのようなオブジェクトはそれ自体でグリフを描くことはできません。 iglyphoutlinePainterインターフェイスによって説明される外部機能が必要です。 glyphoutlinererderオブジェクトを使用するには、 iglyphoutlinepainterの実装を備えている必要があります。 以下に、このインターフェイスの簡単な実装を見ることができます。 グラフィック描画目標に System.Drawing.Drawing.Drawing.GraphicsPathタイプのオブジェクトを必要とするGlyphoutLinePainterクラスを作成しましょう。

以下はインターフェイスの実装です。後述の CustomDrawText() のオーバーロードと FontWidthToImageWidth() メソッドを GlyphOutlinePainter クラスのメンバーとして追加してください。サンプルプロジェクトでは、同じクラスの 2 つ目の部分宣言にこれらのメンバーを配置しています。

 1// Implement a glyph outline painter
 2
 3public partial class GlyphOutlinePainter : IGlyphOutlinePainter
 4{
 5    private readonly GraphicsPath path;
 6    private PointF currentPoint;
 7
 8    public GlyphOutlinePainter(GraphicsPath path)
 9    {
10        this.path = path;
11    }
12
13    public void MoveTo(MoveTo moveTo)
14    {
15        path.CloseFigure();
16        currentPoint = new PointF((float)moveTo.X, (float)moveTo.Y);
17    }
18
19    public void LineTo(LineTo lineTo)
20    {
21        var next = new PointF((float)lineTo.X, (float)lineTo.Y);
22        path.AddLine(currentPoint, next);
23        currentPoint = next;
24    }
25
26    public void CurveTo(CurveTo curveTo)
27    {
28        var next = new PointF((float)curveTo.X3, (float)curveTo.Y3);
29        path.AddBezier(currentPoint, new PointF((float)curveTo.X1, (float)curveTo.Y1),
30            new PointF((float)curveTo.X2, (float)curveTo.Y2), next);
31        currentPoint = next;
32    }
33
34    public void ClosePath()
35    {
36        path.CloseFigure();
37    }
38}

iglyphoutlinePainter実装の後、そのタイプのオブジェクトを使用して、 glyphoutlinerendererにそれらを渡し、renderglyph() `familyの対応する過負荷の方法を呼び出すことで個々のグリフをレンダリングできます。

一連のテキストをレンダリングするには、各文字にglyphidを取得し、 glyphoutlinerendererタイプのrenderglyph()のメソッドの1つを呼び出し、対応するGlyphの座標を渡す必要があります。

Aspose.fontライブラリを使用してテキストの行を出力する例を見てみましょう。パラメーター - *customdrawText *(文字列テキスト、double fontsize、brush backgroundbrush、brush textbrush、string outfile)を受け入れる customdrawtext()メソッドの形式で構築されます。

指定されたテキストを system.drawing.bitmapオブジェクトに描画する customdrawtext()メソッドを作成し、discに結果のビットマップを保存します。

これには、次の手順が含まれます。

この戦略の補助ステップ

最初のオーバーロードはビットマップを作成し、解放します。2 つ目は呼び出し元が所有するビットマップを受け取り、文字間隔、座標、重ね描き、縦方向の出力に対応します。両方のオーバーロードを GlyphOutlinePainter に追加してください。

 1// Render text with spacing, coordinates, overlays and vertical layout
 2
 3public static void CustomDrawText(string text, IFont font, double fontSize,
 4    Brush backgroundBrush, Brush textBrush, string outFile)
 5{
 6    using var bitmap = new Bitmap(960, 720);
 7    CustomDrawText(text, font, fontSize, backgroundBrush, textBrush, outFile, bitmap);
 8}
 9
10public static void CustomDrawText(string text, IFont font, double fontSize,
11    Brush backgroundBrush, Brush textBrush, string outFile, Bitmap bitmap,
12    double kerningCoefficient = 1, double coordinateX = 0, double coordinateY = 0, bool topDown = false)
13{
14    const double dpi = 300;
15    double scale = fontSize * dpi / 72;
16    bitmap.SetResolution((float)dpi, (float)dpi);
17    using (Graphics graphics = Graphics.FromImage(bitmap))
18    {
19        // A transparent background preserves an existing image for overlays.
20        graphics.FillRectangle(backgroundBrush, 0, 0, bitmap.Width, bitmap.Height);
21        graphics.SmoothingMode = SmoothingMode.HighQuality;
22        GlyphId? previousGid = null;
23        double glyphXCoordinate = coordinateX;
24        double glyphYCoordinate = coordinateY + scale;
25
26        foreach (char character in text)
27        {
28            GlyphId gid = font.Encoding.DecodeToGid(character);
29            if (gid == null) continue;
30            Glyph glyph = font.GlyphAccessor.GetGlyphById(gid);
31            if (glyph == null) continue;
32
33            if (previousGid != null)
34            {
35                if (topDown)
36                    glyphYCoordinate += scale;
37                else
38                {
39                    double advance = FontWidthToImageWidth(font.Metrics.GetGlyphWidth(previousGid),
40                        glyph.SourceResolution, fontSize, dpi);
41                    double kerning = font.Metrics.GetKerningValue(previousGid, gid)
42                        / (double)glyph.SourceResolution * scale;
43                    // Like the source example, the coefficient scales the whole advance.
44                    glyphXCoordinate += (advance + kerning) * kerningCoefficient;
45                }
46            }
47
48            using var path = new GraphicsPath();
49            var painter = new GlyphOutlinePainter(path);
50            var renderer = new GlyphOutlineRenderer(painter);
51            var matrix = new TransformationMatrix(new double[]
52            {
53                scale, 0, 0, -scale, glyphXCoordinate, glyphYCoordinate
54            });
55            renderer.RenderGlyph(font, gid, matrix);
56            path.FillMode = FillMode.Winding;
57            graphics.FillPath(textBrush, path);
58            previousGid = gid;
59        }
60    }
61    // The caller owns the supplied bitmap and may reuse it for another overlay.
62    bitmap.Save(outFile, ImageFormat.Png);
63}

フォント単位の幅をピクセルに変換する次の補助メソッドも、同じクラスに追加してください。

1// Convert font units to image pixels
2
3private static double FontWidthToImageWidth(double width, int fontSourceResolution,
4    double fontSize, double dpi = 300)
5{
6    return width / fontSourceResolution * fontSize * dpi / 72;
7}

この例では「Hello world」を、Verdana では白地に黒、Lato では黄色地に青で描画します。結果は Custom_Verdana.png と Custom_Lato.png に保存されます。

 1// Render two fonts with a custom glyph painter
 2
 3string verdanaPath = Path.Combine(DataDir, "TTF", "verdana.ttf");
 4string latoPath = Path.Combine(DataDir, "TTF", "LatoWeb-Regular.ttf");
 5Font verdana = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(verdanaPath)));
 6Font lato = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(latoPath)));
 7string verdanaOutput = Path.Combine(OutputDir, "Custom_Verdana.png");
 8string latoOutput = Path.Combine(OutputDir, "Custom_Lato.png");
 9GlyphOutlinePainter.CustomDrawText("Hello world", verdana, 24, Brushes.White, Brushes.Black, verdanaOutput);
10GlyphOutlinePainter.CustomDrawText("Hello world", lato, 24, Brushes.Yellow, Brushes.Blue, latoOutput);

実行結果:

Verdana によるカスタムテキスト描画 Verdana

Lato によるカスタムテキスト描画 Lato

カーニング

補助メソッドはフォントからペアカーニングを取得します。kerningCoefficient: 1.25 は、前のグリフの幅とペアカーニングを合わせた水平方向の送り量全体を 25% 増やします。この例は Verdana を使用し、IncreasedSpacing.png に保存します。

1// Increase the horizontal glyph advance
2
3string fontPath = Path.Combine(DataDir, "TTF", "verdana.ttf");
4Font font = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(fontPath)));
5string outFile = Path.Combine(OutputDir, "IncreasedSpacing.png");
6using var bitmap = new Bitmap(960, 720);
7GlyphOutlinePainter.CustomDrawText("Hello world", font, 18, Brushes.White, Brushes.Black,
8    outFile, bitmap, kerningCoefficient: 1.25);

実行結果:

間隔係数 1.25 の Verdana 間隔係数 1.25 の Verdana

座標によるテキストのレンダリング

coordinateX と coordinateY でテキストを配置します。最初のベースラインは coordinateY に fontSize * 300 / 72 ピクセルを加えた位置です。18 ポイントの場合、coordinateX: 300 と coordinateY: 225 で (300, 300) に配置されます。結果は PositionedText.png に保存されます。

1// Position text at explicit coordinates
2
3string fontPath = Path.Combine(DataDir, "TTF", "verdana.ttf");
4Font font = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(fontPath)));
5string outFile = Path.Combine(OutputDir, "PositionedText.png");
6using var bitmap = new Bitmap(960, 720);
7// At 18 points and 300 DPI the 75-pixel baseline offset makes the baseline Y=300.
8GlyphOutlinePainter.CustomDrawText("Hello world", font, 18, Brushes.White, Brushes.Black,
9    outFile, bitmap, coordinateX: 300, coordinateY: 225);

実行結果:

Verdana、最初のベースラインは X=300、Y=300 Verdana、最初のベースラインは X=300、Y=300

画像にテキストを追加する方法

既存の画像にテキストを追加するには、ビットマップと透明な背景ブラシを共通の補助メソッドに渡します。透明なブラシは既存のピクセルを保持します。

前述のビットマップを受け取る CustomDrawText() オーバーロードは、この処理にも対応しています。渡された画像に描画して PNG として保存しますが、ビットマップの所有権は呼び出し元に残ります。

この例は OutputDir に OverlayBase.png を作成し、その画像を開いて灰色の影と茶色の注釈を追加します。Shadow.png と ShadowAnnotated.png に別々に保存するため、外部の入力画像は不要です。

 1// Add a shadow and annotation to an existing image
 2
 3string fontPath = Path.Combine(DataDir, "TTF", "verdana.ttf");
 4Font font = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(fontPath)));
 5string inputImagePath = Path.Combine(OutputDir, "OverlayBase.png");
 6GlyphOutlinePainter.CustomDrawText("Hello world", font, 17, Brushes.White, Brushes.Black, inputImagePath);
 7using var bitmap = new Bitmap(inputImagePath);
 8string shadowFile = Path.Combine(OutputDir, "Shadow.png");
 9GlyphOutlinePainter.CustomDrawText("Hello world", font, 17, Brushes.Transparent, Brushes.Gray,
10    shadowFile, bitmap, coordinateX: -3);
11string annotatedFile = Path.Combine(OutputDir, "ShadowAnnotated.png");
12GlyphOutlinePainter.CustomDrawText("<= Shadow effect", font, 17, Brushes.Transparent, Brushes.Brown,
13    annotatedFile, bitmap, coordinateX: 400);

実行結果:

影付きの Verdana 影付きの Verdana

影と注釈付きの Verdana。注釈は幅 960 ピクセルのキャンバスの右端で切れています。 影と注釈付きの Verdana。注釈は幅 960 ピクセルのキャンバスの右端で切れています。

テキストを上から下に出力します

同じオーバーロードで topDown: true を指定すると、上から下に描画できます。最初のグリフを初期ベースラインに配置し、以降の各グリフを fontSize * 300 / 72 ピクセルずつ下に送ります。

この例では「Top down」を Verdana で X=400 に描画し、TopDown.png に保存します。coordinateY がゼロ、フォントサイズが 18 ポイントの場合、最初のベースラインは Y=75 ピクセルです。

1// Render text vertically from top to bottom
2
3string fontPath = Path.Combine(DataDir, "TTF", "verdana.ttf");
4Font font = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(fontPath)));
5string outFile = Path.Combine(OutputDir, "TopDown.png");
6using var bitmap = new Bitmap(960, 720);
7GlyphOutlinePainter.CustomDrawText("Top down", font, 18, Brushes.White, Brushes.Black,
8    outFile, bitmap, coordinateX: 400, topDown: true);
Example-RenderTopDown.cs hosted with ❤ by GitHub

実行結果:

Verdana、上から下への描画 Verdana、上から下への描画

追加情報

補助メソッドは 300 DPI を使用します。scale = fontSize * dpi / 72 はフォントサイズをポイントからピクセルに変換します。glyphXCoordinate と glyphYCoordinate はグリフのベースライン位置を表します。横方向の出力では、次の送り量は前のグリフの幅とフォントのペアカーニングの合計であり、kerningCoefficient がその合計を拡大・縮小します。