I was trying to change the font in my IMagick project. I wanted to use a custom fonts, but apparently it does not work!
Here is my code:
PrivateFontCollection modernFont = new PrivateFontCollection();
modernFont.AddFontFile(path);
var readSettings = new MagickReadSettings()
{
FontFamily = "Walrus Bold",
FontPointsize = 130,
TextGravity = Gravity.Center,
StrokeColor = MagickColors.White,
StrokeWidth = 4,
BackgroundColor = MagickColors.Transparent,
Height = 150,
Width = 600
};
using (var image = new MagickImage(path))
{
using (var caption = new MagickImage($"caption:{idolname}", readSettings))
{
image.Composite(caption, textWidth + 90, textHeight + 155, CompositeOperator.Over);
image.Write(path);
}
}
I already printed the name of the font and it's like that in the modernfont.Families method. I tried to use the font in something else and it worked there.
Anyone an idea how I can implement it?
You can also specify the full path to the font instead of the font name:
var readSettings = new MagickReadSettings()
{
Font = path
}
Related
I'm trying to create an image by drawing a text using a TTF font. I'm using .net core 2.1.500 on MacOS, and have mono-libgdiplus v5.6 (installed via brew).
The TTF file is Neo Sans Medium and this is my code (I tried with different TTF fonts, always with the same result)
using (var bmp = new Bitmap(1024, 512))
{
Graphics g = Graphics.FromImage(bmp);
g.Clear(Color.White);
var rectf = new RectangleF(0, 40, 1024, 90);
// If I specify a font that it doesn't know, it defaults to Verdana
var defaultFont = new Font("DefaultFont", 55);
Console.WriteLine($"defaultFont: {defaultFont.Name}"); // => defaultFont: Verdana
g.DrawString("Text with default", defaultFont, Brushes.Black, rectf);
var privateFontCollection = new PrivateFontCollection();
privateFontCollection.AddFontFile("/path/to/Neo_Sans_Medium.ttf");
var fontFamilies = privateFontCollection.Families;
var family = fontFamilies[0];
var familyHasRegular = family.IsStyleAvailable(FontStyle.Regular);
Console.WriteLine($"familyHasRegular: {familyHasRegular}"); // => familyHasRegular: true
var textFont = new Font(family, 55);
Console.WriteLine($"textFont: {textFont.Name}"); // => textFont: Neo Sans
var rectText = new RectangleF(0, 140, 1024 - 50 - 50, 1024 - 50 - 10);
g.DrawString("Text with loaded font", textFont, Brushes.Black, rectText);
g.Flush();
g.Save();
bmp.Save("test.png", ImageFormat.Png);
}
Since it printed textFont: Neo Sans, it seems to me that it was properly loaded (otherwise, it would have defaulted to Verdana).
However, the output I'm getting is this one:
Am I missing something?
I was able to do it using SixLabors.ImageSharp. I also installed SixLabors.Fonts and SixLabors.ImageSharp.Drawing.
With this code:
using (Image<Rgba32> image = new Image<Rgba32>(1024, 512))
{
FontCollection fonts = new FontCollection();
fonts.Install("/path/to/Neo_Sans_Medium.ttf");
var verdana = SystemFonts.CreateFont("Verdana", 55);
var neoSans = fonts.CreateFont("Neo Sans", 55);
image.Mutate(x => x
.BackgroundColor(Rgba32.White)
.DrawText("Text with default", verdana, Rgba32.Black, new PointF(0, 0))
.DrawText("Text with loaded font", neoSans, Rgba32.Black, new PointF(0, 65))
);
image.Save("out.png");
}
I was able to get this:
Hereby example of how to draw with a custom TTF font. No need to install the private font on this system.
The trick is loading the font in a PrivateFontCollection,
then create a new Font using the loaded FontFamily of the collection.
In this example I used a barcode font KixBarcode.
static Bitmap CreateBarcode(string text)
{
var collection = new PrivateFontCollection();
collection.AddFontFile(#"F:\Projects\Tools\Rtf2Pdf\KixBarcode.ttf");
var image = new Bitmap(300, 300);
var g = Graphics.FromImage(image);
var brush = new SolidBrush(Color.Black);
var font = new Font(collection.Families[0], 12);
g.Dispose();
return image;
}
I was able to get this working without switching to a different drawing library. Copy the FFT file to /usr/share/fonts/ and then switch to using a standard font instead of using PrivateFontCollection.
var font = new Font("Your Font Name", 50);
g.DrawString("Hello world", font, Brushes.Black, rectf);
Installing the font may seem like a "hack" but if you are deploying your app in a container it's as simple as copying the TTF in your Dockerfile.
i am trying to measure single chars of different fonts from Google fonts.
I tried a lot, but the proportion of height and width was always wrong...
Here are some of my attempts:
TextRenderer
font:= the bloburi of a Google font-example: "https://github.com/FontFaceKit/open-sans/blob/gh-pages/fonts/Bold/OpenSans-Bold.ttf?raw=true"
FontRequestHelper helper = new FontRequestHelper(font);
iFontCollection = helper.iFontCollection;
FontStyle style = iFontCollection.Families[0].IsStyleAvailable(FontStyle.Bold) ? FontStyle.Bold : FontStyle.Regular;
System.Drawing.Font googlefont = new System.Drawing.Font(iFontCollection.Families[0], tSize, FontStyle.Regular);
size = TextRenderer.MeasureText("A", googlefont);
MeasureString
i tried different ones, always not accurated...
SizeF sizeFf = new SizeF();
using (var image = new Bitmap(1, 1))
{
using (var g = Graphics.FromImage(image))
{
sizeFf = g.MeasureString("A", googlefont);
}
}
or
using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
{
sizeFf = g.MeasureString("A", googlefont);
}
I dont need the exact width and height, the right proportion would be also reasonable. Online i only find this two solutions as good... Why does it not work for me?
Thx a lot
I have made an application which generates me a QR Code in a PNG image, but now I have to insert the text from QR Code next to the QR Code image.
I don't have any experience using ZXing Library but I'm thinking that it may contain an option for this...
Example:
Code:
namespace QR_Code_with_WFA
{
public void CreateQRImage(string inputData)
{
if (inputData.Trim() == String.Empty)
{
System.Windows.Forms.MessageBox.Show("Data must not be empty.");
}
BarcodeWriter qrcoder = new ZXing.BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new ZXing.QrCode.QrCodeEncodingOptions
{
ErrorCorrection = ZXing.QrCode.Internal.ErrorCorrectionLevel.H,
Height = 250,
Width = 250
}
};
string tempFileName = System.IO.Path.GetTempPath() + inputData + ".png";
Image image;
String data = inputData;
var result = qrcoder.Write(inputData);
image = new Bitmap(result);
image.Save(tempFileName);
System.Diagnostics.Process.Start(tempFileName);
}
}
Well, ZXing.BarcodeWriter.Options has property PureBarcode, which will put source text into generated image when set to false.
Unfortunately it has no effect when format of barcode is BarcodeFormat.QR_CODE (and it is by design).
But you can draw your text manually after you've generated barcode image:
var result = qrcoder.Write(inputData);
using (var g = Graphics.FromImage(result))
using (var font = new Font(FontFamily.GenericMonospace, 12))
using (var brush = new SolidBrush(Color.Black))
using(var format = new StringFormat(){Alignment = StringAlignment.Center})
{
int margin = 5, textHeight = 20;
var rect = new RectangleF(margin, result.Height - textHeight,
result.Width - 2 * margin, textHeight);
g.DrawString(inputData, font, brush, rect, format);
}
result.Save(tempFileName);
Note you can select your own font size and fontfamily which will better suite your goals.
Update:
In the case you're trying to place text to the right from image - you have to "extend" to the right your generated image first, and then draw text:
var result = qrcoder.Write(inputData);
int textWidth = 200, textHeight = 20;
// creating new bitmap having imcreased width
var img = new Bitmap(result.Width + textWidth, result.Height);
using (var g = Graphics.FromImage(img))
using (var font = new Font(FontFamily.GenericMonospace, 12))
using (var brush = new SolidBrush(Color.Black))
using (var bgBrush = new SolidBrush(Color.White))
using (var format = new StringFormat() { Alignment = StringAlignment.Near })
{
// filling background with white color
g.FillRectangle(bgBrush, 0, 0, img.Width, img.Height);
// drawing your generated image over new one
g.DrawImage(result, new Point(0,0));
// drawing text
g.DrawString(inputData, font, brush, result.Width, (result.Height - textHeight) / 2, format);
}
img.Save(tempFileName);
I'm loading an embedded font using this code:
PrivateFontCollection pfc = new PrivateFontCollection(); //declared outside this function
using (Stream fontStream = GetType().Assembly.GetManifestResourceStream("NucWar.BSOD_Font.ttf"))
{
if (null == fontStream)
{
return;
}
int fontStreamLength = (int)fontStream.Length;
IntPtr data = Marshal.AllocCoTaskMem(fontStreamLength);
byte[] fontData = new byte[fontStreamLength];
fontStream.Read(fontData, 0, fontStreamLength);
Marshal.Copy(fontData, 0, data, fontStreamLength);
pfc.AddMemoryFont(data, fontStreamLength);
Marshal.FreeCoTaskMem(data);
}
And that works fine. If I throw a breakpoint down at the end I can see the font is successfully loaded. If I wire-up the Paint event, and use this:
bool bold = false;
bool italic = false;
e.Graphics.PageUnit = GraphicsUnit.Point;
using (SolidBrush b = new SolidBrush(Color.Black))
{
int y = 5;
foreach (FontFamily fontFamily in pfc.Families)
{
if (fontFamily.IsStyleAvailable(FontStyle.Regular))
{
using (Font font = new Font(fontFamily, 32, FontStyle.Regular))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
if (fontFamily.IsStyleAvailable(FontStyle.Bold))
{
bold = true;
using (Font font = new Font(fontFamily, 32, FontStyle.Bold))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
if (fontFamily.IsStyleAvailable(FontStyle.Italic))
{
italic = true;
using (Font font = new Font(fontFamily, 32, FontStyle.Italic))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
if (bold && italic)
{
using (Font font = new Font(fontFamily, 32, FontStyle.Bold | FontStyle.Italic))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
using (Font font = new Font(fontFamily, 32, FontStyle.Underline))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
y += 40;
}
using (Font font = new Font(fontFamily, 32, FontStyle.Strikeout))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
}
}
that too works fine, the font is painted on the form 5 times as it should.
So I find it very confusing when I use this function:
//Yes, pts is a valid size. eg 16, 20, 22, 30
private void AdjustFontSize(float pts)
{
int count = 0;
//_yPos is a dict<string, int> that contains the Name of each Label control, and its original Y position
// Therefore, Keys contains the Name prop of each label
foreach (var lbl in _yPos.Keys)
{
var con = Controls[lbl] as Label; //Current label
FontFamily f = pfc.Families[0]; //Get the font out of pfc. Debugging confirms that f is not null and has a font in it.
//Why this no work? It works fine if I use a built in font, like "Times"
con.Font = new Font(f, pts, FontStyle.Regular);
//Messing with the location prop, still working on it. Probably not important
con.Location = new Point(con.Location.X, (int) (_yPos[lbl] + Math.Pow(1.15, (int) pts)*count++));
}
}
And the label font changes to Arial, not me desired font. What is really bothering me is that If I change con.Font = ... to use "Times" instead of f It correctly changes to the Times font. And on top of that, I know the font is loaded properly because the form paints correctly. By that logic, I am changing the font properly, and I'm loading the font properly, so it should work.
You will need to set UseCompatibleTextRendering to true to use a locally loaded font that isn't a part of the windows font library.
A Label has 2 rendering paths the first (and default) is to use GDI rendering which can't use the Font object and needs to convert it to an internal format and expects the actual font to be in the windows library.
The second path used when UseCompatibleTextRendering is true is to use GDI+ and looks a lot like your paint method by using the Graphics.DrawString method and passing in the Font assigned to the label.
You can also set the setting globally rather than on each control by using the Application.SetCompatibleTextRenderingDefault which would already exist in your Program.cs that is created by default with a WinForms application.
While extracting text from PDF I need to extract font-size too. First I had extracted like this:
iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(
curBaseline[Vector.I1],
curBaseline[Vector.I2],
topRight[Vector.I1],
topRight[Vector.I2]);
In this I am not able to get exact font size. After that I tried using renderinfo.gs.fontsize;. In this renderinfo.gs.fontsize I will get a few text font size exact one but few I won't get exact font size. Where I will get font size has "1.0". Can anyone tell me the method I am using is correct. If NO is there any other method to extract font size using iTextSharp. I am using iTextSharp 5.4 version. Thank you in advance.
using System;
using System.Collections;
// code java to C# conversion
public void renderText(TextRenderInfo renderInfo)
{
LineSegment curBaseline = renderInfo.Baseline;
LineSegment curAscentline = renderInfo.AscentLine;
Rectangle rect = new Rectangle(curBaseline.StartPoint.get(ArrayList.I1), curBaseline.StartPoint.get(ArrayList.I2), curAscentline.EndPoint.get(ArrayList.I1), curAscentline.EndPoint.get(ArrayList.I2));
try
{
Console.Write(" [{0,6:F2}, {1,6:F2}, {2,6:F2}] \"{3}\" ({4} at {5,6:F2})\n", rect.Width, rect.Height, getEffectiveFontSize(renderInfo), renderInfo.Text, renderInfo.Font.FullFontName[0], getFontSize(renderInfo));
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Console.Write(e.StackTrace);
}
}
float getEffectiveFontSize(TextRenderInfo renderInfo) throws System.ArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchFieldException, NoSuchMethodException
{
Method convertHeight = typeof(TextRenderInfo).getDeclaredMethod("convertHeightFromTextSpaceToUserSpace", float.TYPE);
convertHeight.Accessible = true;
return (float?)convertHeight.invoke(renderInfo, getFontSize(renderInfo));
}
float getFontSize(TextRenderInfo renderInfo) throws SecurityException, NoSuchFieldException, System.ArgumentException, IllegalAccessException
{
Field gsField = typeof(TextRenderInfo).getDeclaredField("gs");
gsField.Accessible = true;
GraphicsState gs = (GraphicsState) gsField.get(renderInfo);
return gs.FontSize;
}
Hope this would be useful
`
Font arial = FontFactory.GetFont("Arial", 28, Color.GRAY);
Font verdana = FontFactory.GetFont("Verdana", 16, Font.BOLDITALIC, new Color(125, 88, 15));
Font palatino = FontFactory.GetFont("palatino linotype italique",BaseFont.CP1252, BaseFont.EMBEDDED,
10,
Font.ITALIC,
Color.GREEN
);
Font smallfont = FontFactory.GetFont("Arial", 7);
Font x = FontFactory.GetFont("nina fett");
x.Size = 10;
x.SetStyle("Italic");
x.SetColor(100, 50, 200);`
can be used to set font size