I'm drawing strings on an image and saving it as a TIFF. I need to orient the text like this:
desired output
I'm using this code to create the string format:
formatFlags = (StringFormatFlags.NoClip | StringFormatFlags.DirectionVertical | StringFormatFlags.DirectionRightToLeft);
And this is the output:
actual output
How can I simply flip the orientation around?
Update: Based on the comment, I tried this, but it is place my text way up in the corner instead of where it would be if I didn't add in that sample code. I commented out my original DrawString.
protected virtual void AddTextToBackground(Graphics backgroundGfx, FeatureLocation featureLocation, TextFeature textFeature, int equator) {
Font font = CreateFont(textFeature);
Color fontColor = ColorTranslator.FromHtml(textFeature.FontColor);
Brush textBrush = new SolidBrush(fontColor);
// Determine postion of text box
int xPos = featureLocation.XPos - TEXT_RECT_WIDTH / 2;
int adjustedEquatorOffset = CalculateTextEquatorOffset(featureLocation.EquatorOffset);
//int adjustedEquatorOffset = featureLocation.EquatorOffset;
int yPos = CalculateYPos(equator, adjustedEquatorOffset, TEXT_RECT_WIDTH);
// Rectangle is necessary to create centered text using StringFormat in the DrawString call
Rectangle rect = new Rectangle(xPos, yPos, TEXT_RECT_WIDTH, TEXT_RECT_WIDTH);
// Set up alignment
StringFormat stringFormat = new StringFormat {
Alignment = StringAlignment.Center,
LineAlignment = FindStringAlignment(featureLocation.EquatorOffset)
};
// Determine rotation and set format flags
stringFormat.FormatFlags = GetTextFormatFlags(featureLocation.DefaultRotation, textFeature.Rotation);
// Draw text
SizeF sz = backgroundGfx.VisibleClipBounds.Size;
backgroundGfx.TranslateTransform(sz.Width / 2, sz.Height / 2);
backgroundGfx.RotateTransform(45);
//backgroundGfx.DrawString(textFeature.Text, font, textBrush, rect, stringFormat);
backgroundGfx.DrawString(textFeature.Text, font, textBrush, -(sz.Width/2), -(sz.Height/2), stringFormat);
backgroundGfx.ResetTransform();
}
I'm trying to write text inside circle (not centered by rectangle) alignment must be from line to line inside circle.
I have successfully drawn the circle and text. I did research on Stack Overflow and Google without success about putting text inside this circle.
private void Button1_Click(object sender, EventArgs e)
{
System.Drawing.Graphics graphicsObj;
graphicsObj = this.CreateGraphics();
// Create font and brush.
Font drawFont = new Font("Arial", 5);
SolidBrush drawBrush = new SolidBrush(Color.Black);
// Create point for upper-left corner of drawing.
float x = 150.0F;
float y = 50.0F;
// Set format of string.
StringFormat drawFormat = new StringFormat();
drawFormat.FormatFlags = StringFormatFlags.FitBlackBox;
graphicsObj.DrawEllipse(Pens.Red, 20, 20, 350, 350);
graphicsObj.DrawString(richTextBox1.Text.ToString(), drawFont, drawBrush, x, y, drawFormat);
}
Looking for advise, not for exact code..
-> How to establish connection for text alignment based on rectangle.
Expected output like in this image : https://imge.to/i/miFif
exactly same but I need in C# Win.Form -> Wrap text inside a circular div
DrawString has an overload with format options:
...
DrawString(e.Cache, text, rect,
new StringFormat() {
LineAlignment = StringAlignment.Center,
Alignment = StringAlignment.Center
});
Is it possible to get the DrawString method of C# Graphics object returns the text array just how it's rendering to the display?
e.g.
var font = new System.Drawing.Font("Arial", 12);
var stringFormat = new StringFormat(StringFormatFlags.DirectionRightToLeft) { Alignment = StringAlignment.Near};
var rectangle=new RectangleF(0, 0, 100,20);
var text = "hello this بشدة 176.48 إشعارك بأن";
var textArray= gfx.DrawStringOut(text, font, rectangle, stringFormat);
It should return the below image but in text representation.
Does anyone have a tip whereas you could dynamically resize a font to fit a specific area? For example, I have an 800x110 rectangle and I want to fill it with the max size font that would support the entire string I'm trying to display.
Bitmap bitmap = new Bitmap(800, 110);
using (Graphics graphics = Graphics.FromImage(bitmap))
using (Font font1 = new Font("Arial", 120, FontStyle.Regular, GraphicsUnit.Pixel))
{
Rectangle rect1 = new Rectangle(0, 0, 800, 110);
StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;
graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
graphics.DrawString("Billy Reallylonglastnameinstein", font1, Brushes.Red, rect1, stringFormat);
}
bitmap.Save(Server.MapPath("~/Fonts/" + System.Guid.NewGuid() + ".png"));
Obviously that whole name won't render in the space provided at the large font size. There has to be a simple way to do this?
You should do a scale transform on Font.Size the following function is an example of doing that but you can improve it to apply better results.
Here is FindFont function which get a room and a text with prefered size and gives you a font in which you can set that whole text fits the room!
// This function checks the room size and your text and appropriate font
// for your text to fit in room
// PreferedFont is the Font that you wish to apply
// Room is your space in which your text should be in.
// LongString is the string which it's bounds is more than room bounds.
private Font FindFont(
System.Drawing.Graphics g,
string longString,
Size Room,
Font PreferedFont
) {
// you should perform some scale functions!!!
SizeF RealSize = g.MeasureString(longString, PreferedFont);
float HeightScaleRatio = Room.Height / RealSize.Height;
float WidthScaleRatio = Room.Width / RealSize.Width;
float ScaleRatio = (HeightScaleRatio < WidthScaleRatio)
? ScaleRatio = HeightScaleRatio
: ScaleRatio = WidthScaleRatio;
float ScaleFontSize = PreferedFont.Size * ScaleRatio;
return new Font(PreferedFont.FontFamily, ScaleFontSize);
}
For your question you can call it like the following code:
Bitmap bitmap = new Bitmap(800, 110);
using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap))
using (Font font1 = new Font("Arial", 120, FontStyle.Regular, GraphicsUnit.Pixel))
{
Rectangle rect1 = new Rectangle(0, 0, 800, 110);
StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;
graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
Font goodFont = FindFont(graphics, "Billy Reallylonglastnameinstein", rect1.Size, font1);
graphics.DrawString(
"Billy Reallylonglastnameinstein",
goodFont,
Brushes.Red,
rect1,
stringFormat
);
}
I've adapted Saeed's great function to more suit my requirements. Comments explain all:
// You hand this the text that you need to fit inside some
// available room, and the font you'd like to use.
// If the text fits nothing changes
// If the text does not fit then it is reduced in size to
// make it fit.
// PreferedFont is the Font that you wish to apply
// FontUnit is there because the default font unit is not
// always the one you use, and it is info required in the
// constructor for the new Font.
public static void FindGoodFont(Graphics Graf, string sStringToFit,
Size TextRoomAvail,
ref Font FontToUse,
GraphicsUnit FontUnit)
{
// Find out what the current size of the string in this font is
SizeF RealSize = Graf.MeasureString(sStringToFit, FontToUse);
Debug.WriteLine("big string is {0}, orig size = {1},{2}",
sStringToFit, RealSize.Width, RealSize.Height);
if ((RealSize.Width <= TextRoomAvail.Width) && (RealSize.Height <= TextRoomAvail.Height))
{
Debug.WriteLine("The space is big enough already");
// The current font is fine...
return;
}
// Either width or height is too big...
// Usually either the height ratio or the width ratio
// will be less than 1. Work them out...
float HeightScaleRatio = TextRoomAvail.Height / RealSize.Height;
float WidthScaleRatio = TextRoomAvail.Width / RealSize.Width;
// We'll scale the font by the one which is furthest out of range...
float ScaleRatio = (HeightScaleRatio < WidthScaleRatio) ? ScaleRatio = HeightScaleRatio : ScaleRatio = WidthScaleRatio;
float ScaleFontSize = FontToUse.Size * ScaleRatio;
Debug.WriteLine("Resizing with scales {0},{1} chose {2}",
HeightScaleRatio, WidthScaleRatio, ScaleRatio);
Debug.WriteLine("Old font size was {0}, new={1} ",FontToUse.Size,ScaleFontSize);
// Retain whatever the style was in the old font...
FontStyle OldFontStyle = FontToUse.Style;
// Get rid of the old non working font...
FontToUse.Dispose();
// Tell the caller to use this newer smaller font.
FontToUse = new Font(FontToUse.FontFamily,
ScaleFontSize,
OldFontStyle,
FontUnit);
}
This is just an update for #Saeed's FindFont function.
GraphicsUnit.Pixel needs to be added to FindFont function return line. Without GraphicsUnit.Pixel, system dpi will effect the drawn string. Problem will arise when the dpi of system and bitmap mismatches. You can see more detail in this Windows DPI setting affects Graphics.DrawString. Since GraphicsUnit of PreferedFont is already set to GraphicsUnit.Pixel and return font is not set with GraphicsUnit.Pixel. In this case text will go out of the Room dimension, if bitmap dpi is larger than system dpi and font size will go smaller than the expected size if bitmap dpi is smaller than system dpi. Here is the updated function.
private Font FindFont( System.Drawing.Graphics g , string longString , Size Room , Font PreferedFont)
{
SizeF RealSize = g.MeasureString(longString, PreferedFont);
float HeightScaleRatio = Room.Height / RealSize.Height;
float WidthScaleRatio = Room.Width / RealSize.Width;
float ScaleRatio = (HeightScaleRatio < WidthScaleRatio) ? ScaleRatio = HeightScaleRatio : ScaleRatio = WidthScaleRatio;
float ScaleFontSize = PreferedFont.Size * ScaleRatio;
return new Font(PreferedFont.FontFamily, ScaleFontSize,PreferedFont.Style,GraphicsUnit.Pixel);
}
I don't want to bash against saaeds solution which is probably pretty awesome, too. But I found another one on msdn: Dynamic Graphic Text Resizing which worked for me.
public Font GetAdjustedFont(Graphics GraphicRef, string GraphicString, Font OriginalFont, int ContainerWidth, int MaxFontSize, int MinFontSize, bool SmallestOnFail)
{
// We utilize MeasureString which we get via a control instance
for (int AdjustedSize = MaxFontSize; AdjustedSize >= MinFontSize; AdjustedSize--)
{
Font TestFont = new Font(OriginalFont.Name, AdjustedSize, OriginalFont.Style);
// Test the string with the new size
SizeF AdjustedSizeNew = GraphicRef.MeasureString(GraphicString, TestFont);
if (ContainerWidth > Convert.ToInt32(AdjustedSizeNew.Width))
{
// Good font, return it
return TestFont;
}
}
// If you get here there was no fontsize that worked
// return MinimumSize or Original?
if (SmallestOnFail)
{
return new Font(OriginalFont.Name,MinFontSize,OriginalFont.Style);
}
else
{
return OriginalFont;
}
}
Here is my solution that support wrapping.
public static Font GetAdjustedFont(Graphics graphic, string str, Font originalFont, Size containerSize)
{
// We utilize MeasureString which we get via a control instance
for (int adjustedSize = (int)originalFont.Size; adjustedSize >= 1; adjustedSize--)
{
var testFont = new Font(originalFont.Name, adjustedSize, originalFont.Style, GraphicsUnit.Pixel);
// Test the string with the new size
var adjustedSizeNew = graphic.MeasureString(str, testFont, containerSize.Width);
if (containerSize.Height > Convert.ToInt32(adjustedSizeNew.Height))
{
// Good font, return it
return testFont;
}
}
return new Font(originalFont.Name, 1, originalFont.Style, GraphicsUnit.Pixel);
}
How to use:
var font = GetAdjustedFont(drawing, text, originalfont, wrapSize);
drawing.DrawString(text, font, textBrush, new Rectangle(0, 0, wrapSize.Width, wrapSize.Height));
I am using the following code to draw text onto a jpg image but it requires x/y coordinate percision on where to place the text.
var bmp = new Bitmap("C:\\testing\\Given.jpg");
var gra = Graphics.FromImage(bmp);
var text = "The Berman's";
var font = new Font("Segoe Script", 24);
var brush = Brushes.Orange;
var point = new PointF(130, 224);
gra.DrawString(text, font, brush, point);
bmp.Save("C:\\testing\\Custom.jpg");
How would I go about centering text onto an image? I am guessing it would have to do with defining some sort of container (rectangle maybe?) that is the width of the image and centering the text within that? Not sure what the best practice would be for this.
using(var sf = new StringFormat()
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center,
})
{
gra.DrawString(text, font, brush, new Rectangle(0, 0, bmp.Width, bmp.Height), sf);
}