I want to create a default avatar image which is a circle with initials in it. I want to do this on the server side as a png. Is this possible using the .net graphics library?
I ended up doing this. Thanks for pointing me in the right direction TaW
public ActionResult Avatar()
{
using (var bitmap = new Bitmap(50, 50))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.Clear(Color.White);
using (Brush b = new SolidBrush(ColorTranslator.FromHtml("#eeeeee")))
{
g.FillEllipse(b, 0, 0, 49, 49);
}
float emSize = 12;
g.DrawString("AM", new Font(FontFamily.GenericSansSerif, emSize, FontStyle.Regular),
new SolidBrush(Color.Black), 10, 15);
}
using (var memStream = new System.IO.MemoryStream())
{
bitmap.Save(memStream, System.Drawing.Imaging.ImageFormat.Png);
var result = this.File(memStream.GetBuffer(), "image/png");
return result;
}
}
}
Related
i created a function which is drawing a circle with a letter inside.
i write it into a stream and set it to picture box in Zoom Mode.
It looks nice but some pieces of the circle are cut off.
Here is the Code for the Circle:
public MemoryStream GenerateCircle(string name)
{
var avatarString = string.Format("{0}", name[0]).ToUpper();
var bgColour = ColorTranslator.FromHtml("#007FBC");
var bmp = new Bitmap(70, 70);
var sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
var font = new Font("Arial", 34, FontStyle.Bold, GraphicsUnit.Pixel);
var graphics = Graphics.FromImage(bmp);
graphics.Clear(Color.White);
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
Rectangle rect = new Rectangle(0, 0, 70, 70);
Brush b = new SolidBrush(bgColour);
Pen pen = new Pen(bgColour);
graphics.DrawEllipse(pen, rect);
graphics.FillEllipse(b, rect);
graphics.DrawString(avatarString, font, new SolidBrush(Color.WhiteSmoke), 35, 35, sf);
graphics.Flush();
var ms = new MemoryStream();
bmp.Save(ms, ImageFormat.Png);
return ms;
}
i set it like that:
avatarpicturebox.Image = Image.FromStream(GenerateCircle("Test"));
That is what it looks like:
Circle Cuts Off
Can someone help here please?
Just reduce the circle's width and height 1 pixel each to avoid clipping the right and bottom sides due to the pixels offset. Use Rectangle.Inflate method and pass negative width and height values to shrink the destination rectangle to fit.
Modifying your function to return a Bitmap instead of MemoryStream.
public Bitmap GenerateCircle(string name)
{
var bgColour = ColorTranslator.FromHtml("#007FBC");
var bmp = new Bitmap(70, 70, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (var graphics = Graphics.FromImage(bmp))
using (var sf = new StringFormat())
using (var font = new Font("Arial", 34, FontStyle.Bold, GraphicsUnit.Pixel))
using (var b = new SolidBrush(bgColour))
using (var pen = new Pen(bgColour))
{
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
graphics.Clear(Color.White);
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
graphics.PixelOffsetMode = PixelOffsetMode.Half;
Rectangle rect = new Rectangle(Point.Empty, bmp.Size);
rect.Inflate(-2, -2);
graphics.DrawEllipse(pen, rect);
graphics.FillEllipse(b, rect);
graphics.DrawString(name.ToUpper(), font, Brushes.WhiteSmoke, rect, sf);
}
return bmp;
}
And the caller:
private void SomeButton_Click(object sender, EventArgs e)
{
avatarpicturebox.Image?.Dispose();
avatarpicturebox.Image = GenerateCircle("T");
}
Side Notes
Always dispose of the graphics objects you create either by calling explicitly the .Dispose method or by creating them with using keyword.
Use the Graphics.DrawString overloads that take a Rectangle and StringFormat params to draw the strings. Use the later to dictate how and where the string should be drawn in the given Rectangle. See also StringFormatFlags enum.
How can i create a thumbnail from a video binary (bytes[])?
I do not have access to the directories, so i can't save the file and the example that I can see (using ffmpeg) to create a thumbnail is from a path.
Is there another way to do it?
Assuming, sampleBytes is our byte[] :
using (MemoryStream ms = new MemoryStream(sampleBytes))
{
Bitmap thumb = new Bitmap(100, 100);
using (Image bmp = Image.FromStream(ms))
{
using (Graphics g = Graphics.FromImage(thumb))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
g.DrawImage(bmp, 0, 0, 100, 100);
}
}
// this can show the result
picBoxOut.Image = thumb;
}
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:
I am trying to print 40x40mm labels from a programmatically created image.
The label must have text on it, and a logo. Since the label is fairly small I am finding myself fiddling with how to do proper smooting, antialias and such.
I have tried multipl settings but I am not sure it's even the right way to go about it.
First I draw the container Bitmap:
private Bitmap DrawLabelCircle()
{
var labelImage = new Bitmap(152, 152);
using (Graphics gfx = Graphics.FromImage(labelImage))
{
var pen = new Pen(Color.Black, 1);
gfx.SmoothingMode = SmoothingMode.AntiAlias;
gfx.DrawEllipse(pen, 1, 1, 150, 150);
}
return labelImage;
}
Then I overlay different text snippets on that container Bitmap
private Bitmap DrawDistributorTextRectangle(string text)
{
var bitmap = new Bitmap(113, 113);
var rectangle = new Rectangle(0, 0, 110, 110);
using (Graphics gfx = Graphics.FromImage(bitmap))
{
gfx.SmoothingMode = SmoothingMode.AntiAlias;
gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
gfx.PixelOffsetMode = PixelOffsetMode.HighQuality;
var font = new Font(FontFamily.GenericSansSerif, 5, FontStyle.Regular, GraphicsUnit.Point);
var brush = new SolidBrush(Color.Black);
gfx.TextRenderingHint = TextRenderingHint.AntiAlias;
gfx.DrawString(text, font, brush, rectangle);
}
bitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
return bitmap;
}
Overlay that text on the previous created Bitmap.
private Bitmap DistributorTextOverlay(Bitmap source, Bitmap overlay)
{
var result = new Bitmap(source.Width, source.Height);
var graphics = Graphics.FromImage(result);
graphics.CompositingMode = CompositingMode.SourceOver;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.DrawImage(source, 0, 0);
graphics.DrawImage(overlay, 120, 0);
return result;
}
And the I save it.
var imageCodecInfo = ImageCodecInfo.GetImageEncoders().First(encoder => encoder.MimeType == "image/png");
var encoderInfo = new EncoderParameters() { Param = { [0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L) } };
image.SetResolution(203, 203);
image.Save("img.png", imageCodecInfo, encoderInfo);
The big challenge here is that the image I get is actually looking alright, all things considered.
But when I print it, it looks terrible pixelated.
I would really like to give some pointers for what settings I should apply to all these bitmaps before saving the final result, and what settings should apply for the final image I save.
I am by no means a .NET graphics expert so all help is much appreciated.
40mm is 1.5748 inches. So if you plan to print it at 300 dpi resolution, your bitmap should be 1.5748*300 = 472 pixels instead of 152.
I am getting a screenshot of the computer, then setting it as a picture box by copying it and then using it but after the first time it does it, it says the picture is being used by another process but im guessing i just dungoofed.
public void UpdatePic()
{
String newtemp = System.Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) + "\\screentemp.png";
if (File.Exists(newtemp)) { File.Delete(newtemp); }
File.Copy(screendirect, newtemp);
Image image = Image.FromFile(newtemp);
try
{
using (Bitmap tempBitmap = new Bitmap(image))
{
Size size = new Size(pictureBox1.Width, pictureBox1.Height);
Bitmap backgroundBitmap = new Bitmap(size.Width, size.Height);
using (Graphics g = Graphics.FromImage(backgroundBitmap))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Get the set of points that determine our rectangle for resizing.
Point[] corners = { new Point(0, 0), new Point(backgroundBitmap.Width, 0), new Point(0, backgroundBitmap.Height)};
g.DrawImage(tempBitmap, corners);
g.Dispose();
}
pictureBox1.Image = backgroundBitmap;
}
}
finally
{
}
}