Textwiedergabe mithilfe der Schriftartenbibliothek | .NET
Überblick
Wenn Sie jemals die Funktion zum Rendern von Text in ein Bild nutzen wollten, erfahren Sie in diesem Artikel, wie Sie dies mit Schriftarten in jedem Format tun können, die von der Schriftartenbibliothek mithilfe der Aspose.Font-API-Lösung unterstützt werden. Mit der Bibliothek können Sie problemlos Text in Bilder umwandeln und jedem Bild Text hinzufügen.
Text rendern
Verwenden Sie die Methode
DrawText der Klasse
RenderingUtils, um Text in ein Bild zu zeichnen. Das Beispiel rendert „Hello world“ in Verdana und speichert den PNG-Stream als Text.png.
Setzen Sie DataDir auf das Verzeichnis mit TTF/verdana.ttf und TTF/LatoWeb-Regular.ttf und OutputDir auf ein vorhandenes Ausgabeverzeichnis. Die Beispiele verwenden die Namespaces Aspose.Font, Aspose.Font.Sources, Aspose.Font.Renderers, System, System.IO. Im Testprojekt stellt BaseTests die Verzeichnisse und die Lizenzeinrichtung bereit.
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}Das Ergebnis der Implementierung:

Mit der Methode DrawText können Sie den Zeilenabstand festlegen und einen automatischen wortweisen Textumbruch durchführen.
Im folgenden Codebeispiel haben wir den Zeilenabstandstyp LineSpacingType.Pixels angegeben und auf 10 festgelegt, und wir haben die maximale Breite des Bildes auf 450 festgelegt.
Der gesamte Text, der im angegebenen Bereich (in unserem Fall 450) nicht korrekt angezeigt werden kann, wird in eine neue Zeile umgebrochen.
Das Beispiel wiederholt „Hello world“ in Verdana, damit der Text die Breite von 450 Pixeln überschreitet und auf weitere Zeilen umbricht. Das Ergebnis wird als WrappedText.png gespeichert:
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}Das Ergebnis der Implementierung:

DrawText() liefert einen PNG-Stream. Die Beispiele setzen dessen Position auf den Anfang, kopieren ihn in eine Datei und geben beide Streams frei.
Die Funktionsfamilie für die Methode „DrawText()“ deckt die Ausgabe von Standardtext oder mehrzeiligem Text ab. In einigen Fällen benötigen Sie jedoch möglicherweise eine benutzerdefinierte Ausgabe des Texts, beispielsweise wenn Sie den Text komprimieren, strecken, in einem Winkel drehen oder etwas anderes möchten. In diesem Fall müssen Sie die Ausgabe an Ihre Bedürfnisse anpassen.
Benutzerdefinierte Textwiedergabe
Die folgenden Beispiele zeichnen Glyphenkonturen mit System.Drawing.Common unter Windows auf einer Zeichenfläche von 960 x 720 Pixeln bei 300 DPI. Importieren Sie zusätzlich die Namespaces Aspose.Font.Glyphs, Aspose.Font.Rendering, Aspose.Font.RenderingPath, System.Drawing, System.Drawing.Drawing2D, System.Drawing.Imaging.
Zum Zeichnen von
Glyphen in Aspose.Font wird eine der RenderGlyph()-Methoden der Klasse
GlyphOutlineRenderer verwendet. Alle diese überladenen Methoden werden in der Schnittstelle
IGlyphRenderer deklariert.
Als Parameter müssen wir diesen Methoden einen Verweis auf die Schriftart, die Glyphen-ID oder den Glyphenindex und die Glyphen-Ausgabekoordinaten übergeben. Zur Übergabe des letzten Parameters wird eine spezielle Matrix verwendet, die durch das Objekt Aspose.Font TransformationMatrix repräsentiert wird.
Im Folgenden zeigen wir, wie Sie Objekte vom Typ
TransformationMatrix verwenden, um Glyphen-Ausgabekoordinaten an Methoden der Familie RenderGlyph() zu übergeben.
Um also eine Glyphe zu zeichnen, müssen wir ein Objekt vom Typ GlyphOutlineRenderer erstellen. Ein solches Objekt kann jedoch nicht alleine eine Glyphe zeichnen. Es erfordert externe Funktionalität, die durch die Schnittstelle IGlyphOutlinePainter beschrieben wird. Um das Objekt GlyphOutlineRenderer verwenden zu können, muss eine Implementierung von IGlyphOutlinePainter bereitgestellt werden.
Unten sehen Sie eine einfache Implementierung dieser Schnittstelle. Erstellen wir die Klasse GlyphOutlinePainter, die ein Objekt vom Typ System.Drawing.Drawing2D.GraphicsPath für grafische Zeichnungsziele erfordert.
Die Schnittstellenimplementierung folgt unten. Fügen Sie die später gezeigten Überladungen von CustomDrawText() und die Methode FontWidthToImageWidth() als Mitglieder zu GlyphOutlinePainter hinzu. Im Beispielprojekt stehen diese Methoden in einer zweiten partiellen Deklaration derselben Klasse.
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}Nach der
IGlyphOutlinePainter-Implementierung können wir Objekte dieses Typs verwenden, um eine einzelne Glyphe zu rendern, indem wir sie an den
GlyphOutlineRenderer übergeben und die entsprechenden überladenen Methoden von RenderGlyph() aufrufen Familie.
Um eine Textzeichenfolge zu rendern, müssen wir die glyphId für jedes Zeichen abrufen und dann mit einem Objekt vom Typ
GlyphOutlineRenderer eine der Methoden der Familie RenderGlyph() aufrufen. Übergabe der Koordinaten des entsprechenden Glyphen.
Schauen wir uns ein Beispiel für die Ausgabe einer Textzeile mithilfe der Aspose.Font-Bibliothek an. Es wird in Form der Methode CustomDrawText() erstellt, die Parameter akzeptiert: CustomDrawText(String Text, IFont Font, Double FontSize, Brush BackgroundBrush, Brush TextBrush, String OutFile).
Erstellen Sie die Methode CustomDrawText(), die den angegebenen Text in das Objekt
System.Drawing.Bitmap zeichnet und die resultierende Bitmap auf der Disc speichert.
Dies umfasst die folgenden Schritte:
- Iterieren Sie alle Symbole in einer Textzeichenfolge.
- Holen Sie sich die Glyphen-ID für jedes verarbeitete Symbol – gid.
- Erstellen Sie ein Objekt vom Typ GlyphOutlinePainter, das vom Rendering-Subsystem zum Zeichnen der aktuellen Glyphe benötigt wird.
- Erstellen Sie ein Objekt vom Typ Aspose.Font.Renderers.GlyphOutlineRenderer und übergeben Sie das gerade erstellte Objekt vom Typ GlyphOutlinePainter an den Konstruktor für GlyphOutlineRenderer. Dieses GlyphOutlineRenderer-Objekt soll bestimmte Glyphen rendern.
- Rendern Sie das aktuell verarbeitete Glyph mit der Methode GlyphOutlineRenderer.RenderGlyph(). Das Objekt TransformationMatrix wird zur Angabe von Glyphenkoordinaten verwendet. Die darzustellende Glyphe wird durch den Parameter gid angegeben.
Hilfsschritte für diese Strategie
- Bei horizontaler Ausgabe bleibt die Grundlinie auf der Y-Achse konstant; bei vertikaler Ausgabe verschiebt sie sich für jede weitere Glyphe.
- Bei horizontaler Ausgabe erhöht sich die X-Koordinate um die Breite der vorherigen Glyphe und das Paar-Kerning, multipliziert mit dem Abstandsfaktor.
- Sowohl „X“- als auch „Y“-Koordinaten werden an das TransformationMatrix-Objekt übergeben, das von GlyphOutlineRenderer zum Zeichnen von Glyphen verwendet wird.
- Der horizontale Vorschub wird für jede weitere Glyphe berechnet; bei vertikaler Ausgabe bleibt die X-Koordinate unverändert.
- Ein Objekt vom Typ GlyphOutlineRenderer zeichnet Glyphen mit Hilfe von GlyphOutlinePainter nicht direkt in Bitmap, sondern in das GraphicsPath-Objekt, das an den Konstruktor für GlyphOutlinePainter übergeben wurde, also wir Verwenden Sie das Objekt vom Typ System.Drawing.Graphics, um GraphicsPath in Bitmap zu zeichnen.
- Die Methode FontWidthToImageWidth() rechnet die Glyphenbreite von Schrifteinheiten in Pixel um.
Die erste Überladung erstellt eine Bitmap und gibt sie frei. Die zweite nimmt eine Bitmap entgegen, die dem aufrufenden Code gehört, und unterstützt Abstände, Koordinaten, Überlagerungen und vertikale Ausgabe. Fügen Sie beide Überladungen zu GlyphOutlinePainter hinzu:
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}Fügen Sie dieser Klasse die Hilfsmethode zur Umrechnung der Breite von Schrifteinheiten in Pixel hinzu:
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}Das Beispiel rendert „Hello world“ in Verdana schwarz auf Weiß und in Lato blau auf Gelb. Die Ergebnisse werden als Custom_Verdana.png und Custom_Lato.png gespeichert:
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);Das Ergebnis der Implementierung:
Verdana
Lato
Kerning
Die Hilfsmethode liest das Paar-Kerning aus der Schrift. kerningCoefficient: 1.25 vergrößert den gesamten horizontalen Vorschub (Breite der vorherigen Glyphe plus Paar-Kerning) um 25 %. Das Beispiel verwendet Verdana und speichert 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);Das Ergebnis der Implementierung:
Verdana mit einem Abstandsfaktor von 1.25
Text anhand von Koordinaten rendern
Positionieren Sie den Text mit coordinateX und coordinateY. Für die erste Grundlinie addiert die Methode fontSize * 300 / 72 Pixel zu coordinateY. Bei 18 Punkt setzen coordinateX: 300 und coordinateY: 225 die erste Grundlinie auf (300, 300). Das Ergebnis wird als PositionedText.png gespeichert:
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);Das Ergebnis der Implementierung:
Verdana, erste Grundlinie bei X=300 und Y=300
So fügen Sie den Text zu einem Bild hinzu
Um Text auf ein vorhandenes Bild zu zeichnen, übergeben Sie der gemeinsamen Hilfsmethode eine Bitmap und einen transparenten Hintergrundpinsel. Der transparente Pinsel erhält die vorhandenen Pixel.
Die oben gezeigte Bitmap-Überladung von CustomDrawText() unterstützt diesen Fall bereits. Sie zeichnet auf die übergebene Bitmap und speichert sie als PNG; die Bitmap bleibt im Besitz des aufrufenden Codes.
Das Beispiel erstellt zuerst OverlayBase.png in OutputDir, öffnet dieses Bild und fügt einen grauen Schatten sowie eine braune Beschriftung hinzu. Es speichert Shadow.png und ShadowAnnotated.png getrennt; ein externes Eingabebild ist nicht erforderlich:
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);Das Ergebnis der Implementierung:
Verdana mit Schatten
Verdana mit Schatten und Beschriftung. Die Beschriftung wird am rechten Rand der 960 Pixel breiten Zeichenfläche abgeschnitten.
Ausgabe des Textes von oben nach unten
Dieselbe Überladung unterstützt mit topDown: true die vertikale Ausgabe. Sie setzt die erste Glyphe auf die erste Grundlinie und verschiebt jede weitere Glyphe um fontSize * 300 / 72 Pixel nach unten.
Das Beispiel rendert „Top down“ in Verdana bei X=400 und speichert TopDown.png. Bei coordinateY gleich null und 18 Punkt liegt die erste Grundlinie bei Y=75 Pixeln:
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);Das Ergebnis der Implementierung:
Verdana, von oben nach unten
Weitere Informationen
Die Hilfsmethode verwendet 300 DPI. scale = fontSize * dpi / 72 rechnet die Schriftgröße von Punkt in Pixel um. glyphXCoordinate und glyphYCoordinate bestimmen die Position der Glyphengrundlinie. Bei horizontaler Ausgabe umfasst der nächste Vorschub die Breite der vorherigen Glyphe und das Paar-Kerning der Schrift; kerningCoefficient skaliert deren Summe.