I have some code that uses System.Windows.Forms.DataVisualization.Charting; to generate a chart and create a bitmap image
private Bitmap GetTargetGradingImage(int sessionsTrained, int target, int height, int width)
{
const string TargetSeries = "TargetSeries";
var chart = new Chart
{
Height = height,
Width = width
};
chart.ChartAreas.Add(new ChartArea()
{
Name = "ChartArea1"
});
chart.Series.Clear();
chart.Series.Add(new Series()
{
Name = TargetSeries,
IsVisibleInLegend = true,
ChartType = SeriesChartType.Column,
Color = Color.Green
});
chart.Series[TargetSeries].ChartArea = chart.ChartAreas[0].Name;
string[] XPointMember = new string[2];
int[] YPointMember = new int[2];
XPointMember[0] = "Sessions";
YPointMember[0] = sessionsTrained;
XPointMember[1] = "Target";
YPointMember[1] = target;
chart.Series[TargetSeries].Points.DataBindXY(XPointMember, YPointMember);
chart.Invalidate();
var bitmap = new Bitmap(chart.Size.Width, chart.Size.Height, PixelFormat.Format32bppArgb);
chart.DrawToBitmap(bitmap, chart.Bounds);
//chart.DrawToBitmap(bitmap, new Rectangle(0, 0, bitmap.Size.Width, bitmap.Size.Height));
return bitmap;
}
This works fine on my dev system but not when published to an Azure website. The images are blank.
The images are being used for inclusion in html emails.
Any ideas?
Cracked it.
Didn't need the chart.DrawToBitmap bit at all
This works
using (var chartImage = new MemoryStream())
{
chart.SaveImage(chartImage, ChartImageFormat.Png);
targetBuf = Convert.ToBase64String(chartImage.ToArray());
}
This gives me a Base64 encoded string that I can use in an img tag
I'm working on a task that draw a string on an image.
but the result image is not same with source code that I wrote down.
following image shows the font size difference.
red text is written in NanumSquare font 18px in window paint.
and the black text date below red text is also NanumSquare font 18px. It is written with C# source code.
following is my source code. C#.
static void Main(string[] args)
{
DrawTextToImageSave("webPrint_back.png");
}
public static void DrawTextToImageSave(string path)
{
//png to bitmap
Image Dummy = Image.FromFile(path);
using (Bitmap bitmap = (Bitmap)Dummy)
{//load the image file
using (Graphics graphics = Graphics.FromImage(bitmap))
{
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
var titleFont = new Font("NanumSquareOTF ExtraBold", 25);
var bodyFont = new Font("NanumSquareOTF Regular", 25);
graphics.DrawString("DATE", titleFont, System.Drawing.Brushes.Black, new PointF(401.5f, 863.5f)); //comment 1
graphics.DrawString(DateTime.Now.ToString("yyyy.MM.dd"), bodyFont, System.Drawing.Brushes.Black, new PointF(345, 885f));
graphics.DrawString("LOCATION", titleFont, System.Drawing.Brushes.Black, new PointF(344, 919.5f));
graphics.DrawString(System.DateTime.Now.ToString("yyyyMMddHHmmss") , bodyFont, System.Drawing.Brushes.Black, new PointF(267f, 946f));
WriteableBitmap bitmapimg = Generator128Code("STACKOVERFLOW", 110, 110);
bitmapimg = resize_image(bitmapimg, 1.4); //comment 2
var stream = new MemoryStream();
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapimg));
encoder.Save(stream);
byte[] buffer = stream.GetBuffer();
var qrBitmap = new System.Drawing.Bitmap(new MemoryStream(buffer));
graphics.DrawImage(qrBitmap, 485f, 855f);
}
bitmap.Save( "output_WebPrintBack.png", ImageFormat.Png);
}
}
see comment 1. I expect it draws exactly 18px font. but It does not.
I have also same problem on drawing qrcode with zxing.
without comment2 code I get a ~90 px qr code size.
public static WriteableBitmap Generator128Code(string contents, int width, int height)
{
if (string.IsNullOrEmpty(contents))
{
return null;
}
EncodingOptions options = null;
BarcodeWriter writer = null;
options = new QrCodeEncodingOptions
{
CharacterSet = "UTF-8",
Width = width,
Height = height,
ErrorCorrection = ErrorCorrectionLevel.H,
Margin = 0
};
writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = options
};
WriteableBitmap bitmap = writer.Write(contents);
return bitmap;
}
static WriteableBitmap resize_image(WriteableBitmap img, double scale)
{
BitmapSource source = img;
var s = new ScaleTransform(scale, scale);
var res = new TransformedBitmap(img, s);
return convert_BitmapSource_to_WriteableBitmap(res);
}
static WriteableBitmap convert_BitmapSource_to_WriteableBitmap(BitmapSource source)
{
// Calculate stride of source
int stride = source.PixelWidth * (source.Format.BitsPerPixel / 8);
// Create data array to hold source pixel data
byte[] data = new byte[stride * source.PixelHeight];
// Copy source image pixels to the data array
source.CopyPixels(data, stride, 0);
// Create WriteableBitmap to copy the pixel data to.
WriteableBitmap target = new WriteableBitmap(source.PixelWidth
, source.PixelHeight, source.DpiX, source.DpiY
, source.Format, null);
// Write the pixel data to the WriteableBitmap.
target.WritePixels(new Int32Rect(0, 0
, source.PixelWidth, source.PixelHeight)
, data, stride, 0);
return target;
}
with multiplying x 1.4 with its size, I can get similar result that I want.
why this difference has occured?
size of origin image is also 638px * 1010px. following image is origin image.
thank you for reading. and I apologize my poor English skill.
Edit
following source is executable with Console .net framework.
I retry with this source code but the result was same. :( ...
following source code is full source code.
you need png file that named "webPrint_back.png". and size 638x1010 . https://dummyimage.com/
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using ZXing;
using ZXing.Common;
using ZXing.QrCode;
using ZXing.QrCode.Internal;
using BarcodeWriter = ZXing.Presentation.BarcodeWriter;
namespace bitmapTest
{
class Program
{
static void Main(string[] args)
{
DrawTextToImageSave("webPrint_back.png");
}
public static void DrawTextToImageSave(string path)
{
//png to bitmap
Image Dummy = Image.FromFile(path);
using (Bitmap bitmap = (Bitmap)Dummy)
{//load the image file
using (Graphics graphics = Graphics.FromImage(bitmap))
{
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
var titleFont = new Font("NanumSquareOTF ExtraBold", 18);
var bodyFont = new Font("NanumSquareOTF Regular", 18);
graphics.DrawString("DATE", titleFont, System.Drawing.Brushes.Black, new PointF(401.5f, 863.5f)); //comment 1
graphics.DrawString(DateTime.Now.ToString("yyyy.MM.dd"), bodyFont, System.Drawing.Brushes.Black, new PointF(345, 885f));
graphics.DrawString("LOCATION", titleFont, System.Drawing.Brushes.Black, new PointF(344, 919.5f));
graphics.DrawString(System.DateTime.Now.ToString("yyyyMMddHHmmss") , bodyFont, System.Drawing.Brushes.Black, new PointF(267f, 946f));
WriteableBitmap bitmapimg = Generator128Code("STACKOVERFLOW", 110, 110);
bitmapimg = resize_image(bitmapimg, 1.4); //comment 2
var stream = new MemoryStream();
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapimg));
encoder.Save(stream);
byte[] buffer = stream.GetBuffer();
var qrBitmap = new System.Drawing.Bitmap(new MemoryStream(buffer));
graphics.DrawImage(qrBitmap, 485f, 855f);
}
bitmap.Save( "output_WebPrintBack.png", ImageFormat.Png);
}
}
public static WriteableBitmap Generator128Code(string contents, int width, int height)
{
if (string.IsNullOrEmpty(contents))
{
return null;
}
EncodingOptions options = null;
BarcodeWriter writer = null;
options = new QrCodeEncodingOptions
{
CharacterSet = "UTF-8",
Width = width,
Height = height,
ErrorCorrection = ErrorCorrectionLevel.H,
Margin = 0
};
writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = options
};
WriteableBitmap bitmap = writer.Write(contents);
return bitmap;
}
static WriteableBitmap resize_image(WriteableBitmap img, double scale)
{
BitmapSource source = img;
var s = new ScaleTransform(scale, scale);
var res = new TransformedBitmap(img, s);
return convert_BitmapSource_to_WriteableBitmap(res);
}
static WriteableBitmap convert_BitmapSource_to_WriteableBitmap(BitmapSource source)
{
// Calculate stride of source
int stride = source.PixelWidth * (source.Format.BitsPerPixel / 8);
// Create data array to hold source pixel data
byte[] data = new byte[stride * source.PixelHeight];
// Copy source image pixels to the data array
source.CopyPixels(data, stride, 0);
// Create WriteableBitmap to copy the pixel data to.
WriteableBitmap target = new WriteableBitmap(source.PixelWidth
, source.PixelHeight, source.DpiX, source.DpiY
, source.Format, null);
// Write the pixel data to the WriteableBitmap.
target.WritePixels(new Int32Rect(0, 0
, source.PixelWidth, source.PixelHeight)
, data, stride, 0);
return target;
}
}
}
I found the factor that makes font size is smaller than I expected.
First, source code that I posted works bad with PNG File with "24 bit depth"(without transparent background).
but PNG file with "32 bit depth"(with transparent background), Fontsize works well.
I don't know why It happened.
Second, the barcode made with zxing.net nuget. internally has padding with its border. the problem is that padding size depends on string length. longer string length makes more smaller barcode size and more bigger padding.
following source is my solution for barcode zxing.net nuget
WriteableBitmap bitmapimg = Generator128Code(StaticCommon.localConfigModel.cardBack_QRText, 110, 110);
var stream = new MemoryStream();
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapimg));
encoder.Save(stream);
byte[] buffer = stream.GetBuffer();
var qrBitmap = new System.Drawing.Bitmap(new MemoryStream(buffer));
RectangleF recF = new RectangleF(new PointF(477f, 852f), new SizeF(130, 130));
//ZXING PADDING value, padding size depends on QR encoded string length, so I divide with integer 30 and use remainder
int len = StaticCommon.localConfigModel.cardBack_QRText.Length;
int pad = (int)len / 30;
if (len % 30 > 0) pad++;
RectangleF srecF = new RectangleF(pad * 6f, pad * 6f, 110f - pad * 12f, 110 - pad * 12f);
graphics.DrawImage(qrBitmap, recF, srecF, GraphicsUnit.Pixel);
I solved my problem with engineering way, but I hope someone solve this problem with theoretical way. so I remain this question unsolved.
I'm trying to add text to a video. I've been using the Accord framework so far, and this is what I currently have:
using (var vFReader = new VideoFileReader())
{
vFReader.Open(#"\video.mp4");
using (var vFWriter = new VideoFileWriter())
{
vFWriter.Open(#"\video2.mp4", vFReader.Width, vFReader.Height, vFReader.FrameRate, VideoCodec.MPEG4, vFReader.BitRate);
for (var i = 0; i < vFReader.FrameCount; i++)
{
var image = vFReader.ReadVideoFrame();
var graphics = Graphics.FromImage(image);
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.DrawString("Custom text", font, Brushes.White, new Point(vFReader.Width / 2, 25), format);
graphics.Flush();
vFWriter.WriteVideoFrame(image, (uint)i);
}
vFWriter.Flush();
}
}
This is technically working, but the resulting video is in very poor quality compared to the original. What am I doing wrong?
Here is the difference in quality.
Original video:
Edited video:
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#
I'm attempting to convert a text file to an image using a certain font (Courier New). The problem I'm having is that the font is fixed width, but the text is not being rendered that way on the image. Here's the code I'm currently using
var fontName = textToImageSection.GetString("FontName", "Courier New");
var fontSize = textToImageSection.GetInt("FontSize", 12);
textFont = new Font(fontName, fontSize);
var sf = new StringFormat(StringFormatFlags.MeasureTrailingSpaces);
sf.Trimming = StringTrimming.Character;
var text = File.ReadAllText(textFile.Path);
var image = new Bitmap(1, 1);
var textSize = new Size();
using (var g = Graphics.FromImage(image))
textSize = g.MeasureString(text, textFont, int.MaxValue, sf).ToSize();
image = new Bitmap(image, textSize);
using (var g = Graphics.FromImage(image))
{
g.Clear(Color.White);
//g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
g.DrawString(text, textFont, Brushes.Black, borderLeft, borderTop, sf);
}
image.SaveAsTiff(path);
I've been trying different values for TextRenderingHint without much luck and palying around with the StringFormat.
Here's the resulting image
Here's the text in Notepad++ displayed with Courier New Font