This question already has answers here:
Drawing a Rotated Text to an Image in C#
(2 answers)
Closed 7 years ago.
I have made an application which generates me a QR Code in a PNG image, and prints out the text from QR image, but now I need to rotate that text 90 degrees and I can't find a way to do this...I think that the rectangle must be rotated because the text it's inside this rectangle.
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);
var result2 = qrcoder.Write(inputData);
int textWidth = 200, textHeight = 20;
// creating new bitmap having imcreased width
var img = new Bitmap(result2.Width + textWidth, result2.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, result2.Width, (result2.Height - textHeight) / 2, format);
}
img.Save(tempFileName);
}
}
You need to apply a RotateTransform on the Graphics object before drawing the text:
// Change alignment to center so you don't have to do the math yourself :)
using (var format = new StringFormat() { Alignment = StringAlignment.Center })
{
...
// Translate to the point where you want the text
g.TranslateTransform(result2.Width, result2.Height / 2);
// Rotation happens around that point
g.RotateTransform(-90);
// Note that we draw on [0, 0] because we translated our coordinates already
g.DrawString(inputData, font, brush, 0, 0, format);
// When done, reset the transform
g.ResetTransform();
}
You have to rotate full Graphics:
https://msdn.microsoft.com/en-us/library/a0z3f662(v=vs.110).aspx
Similar topic:
Rotated text align in C#
Related
I have some C# code that adds a simple text overlay with a border and semi-transparent background to an image. It works great, but I'm trying to get an equivalent result using Magick.NET. (The straight C# code drops the XMP tags from the original image, and I haven't found a way to deal with that.) Magick.NET handles the XMP tags well, but I'm having trouble replicating the original output.
Original code follows:
using (Image i = Image.FromStream(stream))
{
int width = i.Width;
int height = i.Height;
using (Graphics graphics = Graphics.FromImage(i))
{
string measureString = "my string";
Size stringSize = graphics.MeasureString(measureString, stringFont).ToSize();
Point drawLocation = new Point(width - stringSize.Width - 15, height - stringSize.Height - 15);
Rectangle rect = new Rectangle(drawLocation.X, drawLocation.Y, stringSize.Width, stringSize.Height);
graphics.DrawRectangle(blackPen, rect);
graphics.FillRectangle(fillBrush, rect);
graphics.DrawString(measureString, stringFont, Brushes.Yellow, drawLocation);
}
i.Save(outputFolder + Path.GetFileName(imgFileName));
}
I cobbled this together based on the Magick.NET examples. This get close to what I'm looking for, but adding the border removes the transparency value, and I'm left with a dark gray background, instead of the transparency.
var settings = new MagickReadSettings{
Font = "Calibri",
FillColor=MagickColors.Yellow,
StrokeColor=MagickColors.Black,
TextGravity = Gravity.Center,
BackgroundColor = new MagickColor("#66666699"),
BorderColor = MagickColors.Black,
Height = 250, // height of text box
Width = 680 // width of text box
};
using (var image = new MagickImage(inputFile))
{
using (var caption = new MagickImage($"caption:{myString}", settings))
{
//adding this border removes transparency
// caption.BorderColor = MagickColors.Black;
// caption.Border(1);
image.Composite(caption, Gravity.Southeast, CompositeOperator.Over);
image.Write(outputFile);
}
}
In command line ImageMagick, this seems to work for me in that the background color is transparent gray. The following the result may be what you want:
convert -font ubuntu -fill yellow -stroke black -gravity center -background "#66666699" -bordercolor black -size 250x680 caption:"This Is Some Text" result.png
Note: I used -background, not -backgroundcolor. Also BorderColor is not the color for the outline of the text. That is the stroke. You have not used BorderColor, since you have not specified the Border amount (as in -border in command line), which would outline the image rectangle and not the text.
Due to time constraints with my project, I took a slightly different path to make this work. I wound up creating the transparent overlay using my original .NET drawing code, and passing that as a memory stream to Magick.NET to handle the merge.
Workaround:
string measureString = "build custom string here";
using (var tmpStreamImg = new MemoryStream())
{
// Call custom function to get length of my string
System.Drawing.Size stringSize = MeasureString(measureString, stringFont).ToSize();
Rectangle rect = new Rectangle(0, 0, stringSize.Width, stringSize.Height);
using (Bitmap overlay = new Bitmap(rect.Width, rect.Height))
{
overlay.SetResolution(350, 350);
using (Graphics overlayGraphic = Graphics.FromImage(overlay))
{
overlayGraphic.DrawRectangle(blackPen, rect);
overlayGraphic.FillRectangle(fillBrush, rect);
overlayGraphic.DrawString(measureString, stringFont, Brushes.Yellow, 3, 3);
}
overlay.Save(tmpStreamImg, ImageFormat.Png);
}
tmpStreamImg.Position= 0;
using (var originalImage = new MagickImage(imgFileName))
{
using (var overlayImage = new MagickImage(tmpStreamImg))
{
originalImage.Composite(overlayImage, Gravity.Southeast, CompositeOperator.Over);
originalImage.Write(outputFolder + Path.GetFileName(imgFileName));
}
}
}
Trying to add a watermark image to a png image, i´ve been able to do it, but i want to take out the hardCoded size regulation for the rectangle of the waterMark, and make it always stay in the center of the image. How can i achieve this.
public Form1()
{
InitializeComponent();
picBox.Parent = this;
picBox.Dock = DockStyle.Fill;
picBox.SizeMode = PictureBoxSizeMode.Zoom;
Bitmap Jpg = new Bitmap(#"C:\Users\tferreira\Desktop\213123.PNG");
using (Bitmap Bmp = new Bitmap(#"C:\Users\tferreira\Desktop\logo.png"))
{
using (Bitmap WatermarkBmp = new Bitmap(Bmp, Bmp.Width / 1, Bmp.Height / 1))
{
picBox.Image = WatermarkImage(Jpg, WatermarkBmp, new Point(400, 100), 0.40F);
}
}
}
public Bitmap WatermarkImage(Bitmap ImageToWatermark, Bitmap Watermark, Point WatermarkPosition, float Opacity)
{
using (Graphics G = Graphics.FromImage(ImageToWatermark))
{
using (ImageAttributes IA = new ImageAttributes())
{
ColorMatrix CM = new ColorMatrix();
CM.Matrix33 = Opacity;
IA.SetColorMatrix(CM);
G.DrawImage(Watermark, new Rectangle(WatermarkPosition, Watermark.Size), 0, 0, Watermark.Width, Watermark.Height, GraphicsUnit.Pixel, IA);
}
}
return ImageToWatermark;
}
Right now the images are hardCoded but that will be taken out. If anyone can help me make this watermark allways stay centered i thank you.
I fixed this problem with this nice peace of code.
System.Drawing.Image img = System.Drawing.Image.FromFile(JpgFilePath);
Bitmap jpg = new Bitmap(img);
filePath = JpgFilePath;
int Width = jpg.Width;
int Height = jpg.Height;
jpg.SetResolution(300, 300);
WaterMarked = WatermarkImage(jpg, WaterMarkBit, new Point((Width - WaterMarkBit.Width) / 2, (Height - WaterMarkBit.Height) / 2), 0.4F);
WaterMarked.Save(filePath.Replace(".jpg", "") + ".tif", ImageFormat.Tiff);
filesJpgForTif.Add(JpgFilePath.Replace("jpg", "tif"));
Using the the sizes of the image and sizes of the watermark and divide it by 2 it makes the image always stay centered.
Im drawing Text using the following code onto a Bitmap
GraphicsPath pth = new GraphicsPath();
var style = (int)myfont.Style;
pth.AddString(tcaption.Text, myfont.FontFamily, style, myfont.Size, point, StringFormat.GenericTypographic);
p = new Pen(new SolidBrush(bc), 2f);
mygraphics.DrawPath(p, pth);
I'm using the TextRenderer to measure the size of the string..
int Width = TextRenderer.MeasureText(tcaption.Text, myfont).Width;
But this does not produce the correct size of the drawn string; there is around 20-30% difference from the actual size of the drawn string?
What im i doing wrong? Please advice.
UPDATE:
I want to draw a Text and an Image onto a Bitmap,so inorder to accommodate both i'm creating an Bitmap like this
intWidth = TextRenderer.MeasureText(tcaption.Text, cfont).Width + image.Width;
intHeight = TextRenderer.MeasureText(tcaption.Text, cfont).Height +image.Height;
tempimage= new Bitmap(intWidth, intHeight);
Then i create Graphics object from the Bitmap like this
using (Graphics newg = Graphics.FromImage(tempimage))
#Hans Passant
I have also tried the Graphics.MeasureString as an alternative to TextRenderer
Now i set the position of the text and image-I need to draw the image at the top left corner .. so
imageposy = 0;
imageposx = 10;
textposy = image.Height;
textposx = 0;
Then i draw the text like this
po=new Point(textposx, textposy);
newg.SmoothingMode = SmoothingMode.AntiAlias;
GraphicsPath pth = new GraphicsPath();
var style = (int)myfont.Style;
pth.AddString(tcaption.Text, myfont.FontFamily, style, myfont.Size, po,
StringFormat.GenericTypographic);
newg.FillPath(new SolidBrush(fc), pth);
Now i draw the image like this
Rectangle nrect = new Rectangle(imageposx, imageposy, image.Width,
image.Height);
objGraphics = Graphics.FromImage(tempimage);
objGraphics.DrawImage(image, nrect);
As you have seen i need to add the offset 10 to imageposition x coordinate to correct the measurement issue.
Hope my update throws more light into the question... what im i doing wrong?
Please advice..
instead of using TextRenderer use GraphicsPath:
var path = new GraphicsPath();
path.AddString(text, font.FontFamily, (int)font.Style, size, new Point(0, 0), StringFormat.GenericTypographic);
var area = Rectangle.Round(path.GetBounds());
Here is sample code that generates image with size of text:
private Image DrawText(String text, Font font, int size, Color textColor, Color backColor)
{
var path = new GraphicsPath();
path.AddString(text, font.FontFamily, (int)font.Style, size, new Point(0, 0), StringFormat.GenericTypographic);
var area = Rectangle.Round(path.GetBounds());
Rectangle br = Rectangle.Round(path.GetBounds());
var img = new Bitmap(br.Width, br.Height);
var drawing = Graphics.FromImage(img);
drawing.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
drawing.SmoothingMode = SmoothingMode.HighSpeed;
drawing.Clear(backColor);
drawing.TranslateTransform((img.Width - br.Width) / 2 - br.X, (img.Height - br.Height) / 2 - br.Y);
drawing.FillPath(Brushes.Black, path);
Brush textBrush = new SolidBrush(textColor);
drawing.Save();
textBrush.Dispose();
drawing.Dispose();
return img;
}
Here are sample results:
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);
This question already has answers here:
How to Add the values of List<string> into the List<PictureBox> after encoding it to Barcode in c#
(3 answers)
Closed 9 years ago.
I have an array of type PictureBox. I want to fill it the List of string and then covert it to the Barcode. But I am uncle to convert the string to the PictureBox. Is there any step I can do to make them compatible?
System.Windows.Forms.PictureBox[] PictureBoxArray = new PictureBox[3];
List<string> serial = new List<string>;
public void ConvertToBarCode()
{
BarcodeLib.TYPE barcodetype1 = BarcodeLib.TYPE.CODE39;
BarcodeLib.Barcode bar1 = new BarcodeLib.Barcode();
bar1.IncludeLabel = true;
PictureBoxArray[0] = serial[0]; // Want to Convert String to PictureBox
PictureBoxArray[0].Image = bar1.Encode(barcodetype1, SerialNumberList[0]);
}
I have filles the serial List with the string now just want the conversion.
you want like this.. right?? see this is the representaion of the this string "S1253551" in 3of9 and plain text and finally as image right??
public Image stringToImage(string inputString)
{
string text = inputString.Trim();
Bitmap bmp = new Bitmap(1, 1);
//Set the font style of output image
Font font = new Font("Free 3 of 9", 25, FontStyle.Regular, GraphicsUnit.Pixel);
Font font2 = new Font("Arial", 15, FontStyle.Regular, GraphicsUnit.Pixel);
Graphics graphics = Graphics.FromImage(bmp);
int width = (int)graphics.MeasureString(text, font).Width;
int height = (int)graphics.MeasureString(text, font).Height;
int height2 = (int)graphics.MeasureString(text, font2).Height;
bmp = new Bitmap(bmp, new Size(width, height+height2));
graphics = Graphics.FromImage(bmp);
//Specify the background color of the image
graphics.Clear(Color.Cyan);
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
//Specify the text, font, Text Color, X position and Y position of the image
graphics.DrawString(text, font, new SolidBrush(Color.Black), 0, 0);
graphics.DrawString(text, font2, new SolidBrush(Color.Black), 0, height);
graphics.Flush();
graphics.Dispose();
//if you want to save the image uncomment the below line.
//bmp.Save(#"d:\myimage.jpg", ImageFormat.Jpeg);
return bmp;
}
Remember you must have installed "free 3 of 9" font.
you pass the string "S1253551" and it generate the barcode and add the plain text at bottom and finally return it as image.
Its working code i have tried at my end. Enjoy. :)
Download the working code from here Download