Using .DrawToBitmap - how to change resolution of image? - c#

Im using DrawToBitmap to save some labels as image. I would like to know how to change the resolution of these images, is there a way? Say I have a label with a text and I want to render it to an image file (not posting the full code):
this.label1 = new System.Windows.Forms.Label();
this.label1.AutoSize = true;
this.label1.Font = new System.Drawing.Font("Baskerville Old Face", 36F);
//...
this.label1.Size = new System.Drawing.Size(161, 54);
this.label1.Text = "Output";
//...
//save image:
Bitmap image = new Bitmap(161, 54);
this.label1.DrawToBitmap(image, this.label1.ClientRectangle);
image.Save(#"C:\image.jpg");
This is working fine, I will get something like this:
The resolution is ok, but is it possible to increase it? When I zoom into this image a little, I can see the individual pixels as large blocks:
I know that's normal, because its not a vector graphic and that's fine. I just would like to change it somehow, so that you can zoom in further before seeing individual pixels as large blocks. Any ideas?
Thank you.
Edit: If Im using only black/white images - is it maybe better to save the image as png or gif?

Something like this will do the job, just increase font size used from label:
Bitmap CreateBitmapImage(string text, Font textFont, SolidBrush textBrush)
{
Bitmap bitmap = new Bitmap(1, 1);
Graphics graphics = Graphics.FromImage(bitmap);
int intWidth = (int)graphics.MeasureString(text, textFont).Width;
int intHeight = (int)graphics.MeasureString(text, textFont).Height;
bitmap = new Bitmap(bitmap, new Size(intWidth, intHeight));
graphics = Graphics.FromImage(bitmap);
graphics.Clear(Color.White);
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.DrawString(text, textFont, textBrush,0,0);
graphics.Flush();
return (bitmap);
}

you can achieve this by increasing the value of second parameter of System.Drawing.Font.
this.label1.Font = new System.Drawing.Font("Baskerville Old Face", 1000F);

Related

Failure in writing a BMP file

I am trying to generate a BMP file that has some text. I created a winform application and I can succesfully create the BMP (I displayed it on a picture Box with no problems). However when I save it to a file, I just got a black image.
My code is
private void btnNameUsage_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(width, height);
string name = "Hello how are you";
string date = DateTime.Now.Date.ToString();
Graphics thegraphics = Graphics.FromImage(bmp);
string complete = date+"\n"+name ;
using (Font font1 = new Font("Arial", 24, FontStyle.Regular, GraphicsUnit.Pixel))
using (var sf = new StringFormat()
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center,
})
{
thegraphics.DrawString(complete, font1, Brushes.Black, new Rectangle(0, 0, bmp.Width, bmp.Height), sf);
}
picBoxImage.Image = bmp; //THIS WORKS
//thegraphics.Flush();//I am not sure this is necessary and it changes nothing anyway
bmp.Save(#"theImage.bmp",ImageFormat.Bmp);//I tried only one argument but it gave a png file. Now only a black BMP
}
What am I doing wrong here?
The reason why PNG works and BMP doesn't is that PNG allows transparency in the image. In BMP the transparent parts of your image are rendered black (since it has to drop the alpha channel). Your text is also using a black brush, so you will get a black image.
For on-screen rendering this is not an issue, since there, transparency is supported.

Blurry and large image barcode being generated using a plugin in Windows Form

Going through the steps mentioned here
and using IDAutomationCode39, I am getting the barcode image, however they are very blurr and only scans bigger size images. My barcode id will be upto 30 characters long, which is causing a very wide barcode image. Where could the problem lie? Is it the IDAutomationCode39 or my setting in my button click event below?
private void button1_Click(object sender, EventArgs e)
{
string abbre = GenerateProdCodeFromProductName();
txt2.Text = abbre;
string barcode = txt1.Text;
Bitmap bitm = new Bitmap(barcode.Length * 45, 160);
bitm.SetResolution(240, 240);
using (Graphics graphic = Graphics.FromImage(bitm))
{
Font newfont = new Font("IDAutomationHC39M", 6);
PointF point = new PointF(5f, 5f);
SolidBrush black = new SolidBrush(Color.Black);
SolidBrush white = new SolidBrush(Color.White);
graphic.FillRectangle(white, 0, 0, bitm.Width, bitm.Height);
graphic.DrawString("*" + barcode + "*", newfont, black, point);
}
using (MemoryStream Mmst = new MemoryStream())
{
bitm.Save("ms", ImageFormat.Jpeg);
pictureBox1.Image = bitm;
pictureBox1.Width = bitm.Width;
pictureBox1.Height = bitm.Height;
}
}
Thank you.
I don't see any PlugIn reference in your code, you are just using a Code39 ASCII font to print a Barcode on a Bitmap.
The problem I see is that the size of the resulting Bitmap is unscaled.
What I mean is, you let the size of the Barcode determine the size of the final graphic image.
It is usually the opposite. You have some defined dimensions for a Bitmap, because of layout constraints: you have to print the barcode to a label, for example.
If the generated Barcode is wider than its container, you have to normalize it (scale it to fit).
Here is what I propose. The size of the Bitmap if fixed (300, 150). When the Barcode is generated, its size is scaled to fit the Bitmap size.
The quality of the image is preserved, using an Bicubic Interpolation in case of down scaling. The resulting graphics is also Anti-Aliased.
(Anti-Alias has a good visual render. May not be the best choice for printing. It also depends on the printer.)
The generated Bitmap is then passed to a PictureBox for visualization and saved to disk as a PNG image (this format because of its loss-less compression).
Here is the result:
string Barcode = "*8457QK3P9*";
using (Bitmap bitmap = new Bitmap(300, 150))
{
bitmap.SetResolution(240, 240);
using (Graphics graphics = Graphics.FromImage(bitmap))
{
Font font = new Font("IDAutomationSHC39M", 10, FontStyle.Regular, GraphicsUnit.Point);
graphics.Clear(Color.White);
StringFormat stringformat = new StringFormat(StringFormatFlags.NoWrap);
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
graphics.TextContrast = 10;
PointF TextPosition = new PointF(10F, 10F);
SizeF TextSize = graphics.MeasureString(Barcode, font, TextPosition, stringformat);
if (TextSize.Width > bitmap.Width)
{
float ScaleFactor = (bitmap.Width - (TextPosition.X / 2)) / TextSize.Width;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.ScaleTransform(ScaleFactor, ScaleFactor);
}
graphics.DrawString(Barcode, font, new SolidBrush(Color.Black), TextPosition, StringFormat.GenericTypographic);
bitmap.Save(#"[SomePath]\[SomeName].png", ImageFormat.Png);
this.pictureBox1.Image = (Bitmap)bitmap.Clone();
font.Dispose();
}
}

Cropping Image(From Screen)

I have read many question about this. But my question is little bit different. What i need to do crop image from screen.
There is my codes
Bitmap photo = new Bitmap(Screen.PrimaryScreen.Bounds.Width,Screen.primaryScreen.Bounds.Height)
Graphics gr = Graphics.FromImage(photo);
gr.CopyFromScreen(0,0,0,0 new size(foto.Width,foto.Height));
picturebox1.Image = photo;
And there my crop codes
Rectangle cropRec = new Rectangle(1,1,1,1);
Bitmap target = new Bitmap(cropRec.Width,cropRec.Height);
using(Graphics g = Graphics.FromImage(target))
{
g.DrawImage(photo,new Rentangle(0,0,target.Width,target.Height),cropRec,GraphicsUnit.Pixel);
}
I want to crop middle part of this photo and compare with itself.
Thanks n advance
To symmetrically crop your image as shown in the following sketch, try creating a Bitmap with margins in the X and Y axis and then cropping the screenshot image by using those margins in CopyFromScreen():
Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width - 2 * xmargin, Screen.PrimaryScreen.Bounds.Height - 2 * ymargin);
Graphics graphics = Graphics.FromImage(printscreen as Image);
graphics.CopyFromScreen(xmargin, ymargin, 0, 0, printscreen.Size);

c# write text on bitmap

I have following problem. I want to make some graphics in c# windows form.
I want to read bitmap to my program and after it write some text on this bitmap. In the end I want this picture load to pictureBox. And it's my question. How can I do it?
example, how must it work:
Bitmap a = new Bitmap(#"path\picture.bmp");
a.makeTransparent();
// ? a.writeText("some text", positionX, positionY);
pictuteBox1.Image = a;
Is it possible do to?
Bitmap bmp = new Bitmap("filename.bmp");
RectangleF rectf = new RectangleF(70, 90, 90, 50);
Graphics g = Graphics.FromImage(bmp);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawString("yourText", new Font("Tahoma",8), Brushes.Black, rectf);
g.Flush();
image.Image=bmp;
Very old question, but just had to build this for an app today and found the settings shown in other answers do not result in a clean image (possibly as new options were added in later .Net versions).
Assuming you want the text in the centre of the bitmap, you can do this:
// Load the original image
Bitmap bmp = new Bitmap("filename.bmp");
// Create a rectangle for the entire bitmap
RectangleF rectf = new RectangleF(0, 0, bmp.Width, bmp.Height);
// Create graphic object that will draw onto the bitmap
Graphics g = Graphics.FromImage(bmp);
// ------------------------------------------
// Ensure the best possible quality rendering
// ------------------------------------------
// The smoothing mode specifies whether lines, curves, and the edges of filled areas use smoothing (also called antialiasing).
// One exception is that path gradient brushes do not obey the smoothing mode.
// Areas filled using a PathGradientBrush are rendered the same way (aliased) regardless of the SmoothingMode property.
g.SmoothingMode = SmoothingMode.AntiAlias;
// The interpolation mode determines how intermediate values between two endpoints are calculated.
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Use this property to specify either higher quality, slower rendering, or lower quality, faster rendering of the contents of this Graphics object.
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
// This one is important
g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
// Create string formatting options (used for alignment)
StringFormat format = new StringFormat()
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
// Draw the text onto the image
g.DrawString("yourText", new Font("Tahoma",8), Brushes.Black, rectf, format);
// Flush all graphics changes to the bitmap
g.Flush();
// Now save or use the bitmap
image.Image = bmp;
References
https://msdn.microsoft.com/en-us/library/system.drawing.graphics.smoothingmode(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.drawing.drawing2d.interpolationmode(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.drawing.graphics.pixeloffsetmode(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.drawing.graphics.textrenderinghint(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.drawing.stringformat(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/21kdfbzs(v=vs.110).aspx
You need to use the Graphics class in order to write on the bitmap.
Specifically, one of the DrawString methods.
Bitmap a = new Bitmap(#"path\picture.bmp");
using(Graphics g = Graphics.FromImage(a))
{
g.DrawString(....); // requires font, brush etc
}
pictuteBox1.Image = a;
var bmp = new Bitmap(#"path\picture.bmp");
using( Graphics g = Graphics.FromImage( bmp ) )
{
g.DrawString( ... );
}
picturebox1.Image = bmp;
If you want wrap your text, then you should draw your text in a rectangle:
RectangleF rectF1 = new RectangleF(30, 10, 100, 122);
e.Graphics.DrawString(text1, font1, Brushes.Blue, rectF1);
See: https://msdn.microsoft.com/en-us/library/baw6k39s(v=vs.110).aspx

.NET - Border around resized imaged

I'm trying to resize an image in .NET, but get a faint black border around the resized image. I found a post - http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/cf765094-c8c1-4991-a1f3-cecdbd07ee15/ which from someone who said making the destination rectangle larger than the canvas worked, but this doesn't work for me. It gets riid of the top and left borders, but the right and bottom are still there, and are a full 1px thick black.
Am I missing something? My code is below.
Image image = ... // this is a valid image loaded from the source
Rectangle srcRectangle = new Rectangle(0,0,width, height);
Size croppedFullSize = new Size(width+3,height+3);
Rectangle destRect = new Rectangle(new Point(-1,-1), croppedFullSize);
using(Bitmap newImage = new Bitmap(croppedFullSize.Width, croppedFullSize.Height, format))
using(Graphics Canvas = Graphics.FromImage(newImage)) {
Canvas.SmoothingMode = SmoothingMode.AntiAlias;
Canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
Canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;
Canvas.FillRectangle(Brushes.Transparent, destRect);
Canvas.DrawImage(image, destRect, srcRectangle, GraphicsUnit.Pixel);
newImage.Save(filename, image.RawFormat);
}
Simply provide the DrawImage method with an ImageAttributes instance which has WrapMode set to TileFlipXY. This will prevent the edge from blending against the background color.
For sample code that doesn't leak memory like the other answers here, see this gist
Try it like this, i think i've never got a black border...
If you want to use System.Drawing libraries:
using (var sourceBmp = new Bitmap(sourcePath))
{
decimal aspect = (decimal)sourceBmp.Width / (decimal)sourceBmp.Height;
int newHeight = (int)(newWidth / aspect);
using (var destinationBmp = new Bitmap(newWidth, newHeight))
{
using (var destinationGfx = Graphics.FromImage(destinationBmp))
{
destinationGfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
destinationGfx.DrawImage(sourceBmp, new Rectangle(0, 0, destinationBmp.Width, destinationBmp.Height));
destinationBmp.Save(destinationPath, ImageFormat.Jpeg);
}
}
}
or you can do the same with wpf, like this:
using (var output = new FileStream(outputPath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None))
{
var imageDecoder = BitmapDecoder.Create(inputStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);
var imageFrame = imageDecoder.Frames[0];
decimal aspect = (decimal)imageFrame.Width / (decimal)imageFrame.Height;
var height = (int)(newWidth / aspect);
var imageResized = new TransformedBitmap(imageFrame,new ScaleTransform(
newWidth / imageFrame.Width * Dpi / imageFrame.DpiX,
height / imageFrame.Height * Dpi / imageFrame.DpiY, 0, 0));
var targetFrame = BitmapFrame.Create(imageResized);
var targetEncoder = new JpegBitmapEncoder();
targetEncoder.Frames.Add(targetFrame);
targetEncoder.QualityLevel = 80;
targetEncoder.Save(output);
}
I recommend the WPF way. The compression & quality seems better...
For me it was a bad Bitmap parameter. Instead of this:
new Bitmap(width, height, PixelFormat.Format32bppPArgb);
Just remove the PixelFormat to this:
new Bitmap(width, height);
And everything was ok then.
With the PixelFormat I had black border on the top and left border. Then I tried g.PixelOffsetMode = PixelOffsetMode.HighQuality; which seemed fine at first. But then I noticed light gray borders around the whole image.

Categories