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.
Related
I have successfully generated a BMP file. (I am still tweaking some changes in format I am required to do though). I created a winform with a PictureBox. Following my last question, I now can save the file, but now the bitmap cannot be displayed in the PictureBox. This happened after I changed the palette following this answer to have the alpha of the colors set to 0
My bmp is monochrome as taught in this answer (I wonder whether there could be a simpler way)
My code is
private void btnNameUsage_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(width, height);
// Bitmap bmp = new Bitmap(width, height, PixelFormat.Format1bppIndexed); //This does not work
bmp.SetResolution(300.0F, 300.0F);
string name = "Hello how are you";
string date = DateTime.Now.Date.ToString();
using (Graphics thegraphics = Graphics.FromImage(bmp))
{
string complete = date + "\n" + name ;
thegraphics.FillRectangle(Brushes.White, 0, 0, bmp.Width, bmp.Height);
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);
}
}
//add
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format1bppIndexed);
Bitmap newBitmap = new Bitmap(width, height, bmpData.Stride, PixelFormat.Format1bppIndexed, bmpData.Scan0);
newBitmap.SetResolution(300.0F, 300.0F);
//we modify the palette THIS MAKES THE BMP NOT SHOWN IN PIT BOX
ColorPalette palette = newBitmap.Palette;
palette.Entries[0] = black; //black is a type Color
palette.Entries[1] = white; //white is a type Color
newBitmap.Palette = palette;
picBoxImage.Image = newBitmap; //THIS fails
newBitmap.Save(#"theImage.bmp", ImageFormat.Bmp); //This works!
}
I have to clarify that the generated pallete by default colors are (RGBA) black:000000FF and white: FFFFFFFF (with this palette I can see the bmp in the picbox) but I am changing to black :00000000 and white: FFFFFF00 (as you can see only the A component is changed)
the variables black and white are
Color black = new Color();
Color white = new Color();
white = Color.FromArgb(0, 255, 255, 255); //the 0 is alpha zero
black = Color.FromArgb(0, 0, 0, 0); //the first 0 is alpha zero
I wonder why it is not showing.
As a side question, how can I change the "number of important colors" in the DIB header?
EDIT:
I experimented with the alpha setting (for example 128) and I could see the picture only slightly less bright colors.(as in grey)
This only happens when displaying the bmp. The saved file is correctly black and white
What is the relation between picturebox and alpha...
Alpha denotes the opacity of the color. 0 means the color is totally transparent, i.e. you will only see the canvas/background, 128 means the color is 50% transparent meaning you will see the color and background in the same amount, 255 means full opacity/zero transparency meaning you will only see the color.
In short white is "FFFFFFFF" and black is "FF000000".
If you want to specify colors by their RGB components use the FromArgb method with the three parameters which implicitly sets the alpha channel to 255.
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();
}
}
I am currently making an MVC project where the User will receive a Certificate which is displayed on the page. The Certificate is an image and then Text is used to overlap the image where the Users name and other information will be printed, using css to format the text to the correct part of the image.
As the image and text are technically still separate, saving the image does not save the text on top so what you save is just the template of a certificate and no text.
Is there a way to save both image and text as one, as if the text was pressed onto the image and was the same object? If so, I would appreciate being pointed in the right direction to know how to do this. Any ideas or code to save an image and text as one it would be very helpful.
Thanks.
May this help you
private void makeCertificate(string name, string id, string otherDetails) //You can pass any other details as well
{
System.Drawing.Image PrePrintedCertificate;
name = name.ToUpper();
string PrePrintedCertificateName = "Certificate.jpg"; //Assuming Certificate JPG File is in the bin folder
using (FileStream stream = new FileStream(PrePrintedCertificateName, FileMode.Open, FileAccess.Read))
{
PrePrintedCertificate = System.Drawing.Image.FromStream(stream);
}
RectangleF rectf4Name = new RectangleF(655, 460, 535, 90); //rectf for Name
RectangleF rectf4ID = new RectangleF(655, 560, 400, 40);
System.Drawing.Rectangle rect;
Bitmap picEdit = new Bitmap(PrePrintedCertificate, new System.Drawing.Size(1241, 1756));
using (Graphics g = Graphics.FromImage(picEdit))
{
//g.DrawRectangle(new System.Drawing.Pen(System.Drawing.Color.Red, 2), 662, 530, 90, 40);
//I have used upper line to see where is my RectangleF creating on the image
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
StringFormat sf1 = new StringFormat();
sf1.Alignment = StringAlignment.Near;
//g.DrawImage(codeImage, rect); //If you wanted to draw another image on the certificate image
g.DrawString(name, new System.Drawing.Font("Thaoma", 26, System.Drawing.FontStyle.Bold), System.Drawing.Brushes.Black, rectf4Name, sf);
g.DrawString(Track.Text, new System.Drawing.Font("Thaoma", 14, System.Drawing.FontStyle.Bold), System.Drawing.Brushes.Black, rectf4ID, sf1);
}
try
{
if (File.Exists(id + ".jpg"))
File.Delete(id + ".jpg");
picEdit.Save(id + ".jpg", ImageFormat.Jpeg);
picEdit.Dispose();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
Things to note here is that this image is a A4 size paper image with portrait orientation. You probably need to change Bitmap picEdit = new Bitmap(PrePrintedCertificate, new System.Drawing.Size(1241, 1756)); to Bitmap picEdit = new Bitmap(PrePrintedCertificate, new System.Drawing.Size(1756,1241));
Another thing is the names and other details has been printed on the image with random place but you can see where exactly you wish to print the details.
You can look where it will get printed using g.DrawRectangle(new System.Drawing.Pen(System.Drawing.Color.Red, 2), 662, 530, 90, 40); the Parameters you gonna pass here will be same as the RectangleF Parameters.
Save the graphic as an SVG and add the text using a text object.
You can also use CSS within the SVG to style the text.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<text x="20" y="40">Example SVG text 1</text>
</svg>
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
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);
}