I want to print labels. If I draw to the printing contexts Graphics object, it works without problems. But if I use a temporary Bitmap all the drawn text is pixelated. I recognized that the resolution of the temp Bitmap and the printing Graphics object are different (96 dpi vs. 600 dpi). So I change the Bitmaps resolution to match the printing resolution. So all the drawn text is too big.
I need the temporary Bitmap to rotate the image before printing.
How to get this Bitmap correctly printed?
Pixalated code: (looks bad but has the temporary bitmap)
// print event handler
private void printPage(object sender, PrintPageEventArgs ev)
{
// size of the page
Size s = Form1.getPixelFromCM(Properties.Settings.Default.LabelSize);
// temporary bitmap object
Bitmap bmp = new Bitmap(s.Width, s.Height);
Graphics g = Graphics.FromImage(bmp);
// draw text
labels[printLabelsIndex].PrintLabel(g);
// draw the bitmap to the page
ev.Graphics.DrawImage(bmp, 0, 0);
}
This code produces this print:
High resolution code: (looks good but I need the temporary bitmap!)
// print event handler
private void printPage(object sender, PrintPageEventArgs ev)
{
// draw text directly to print context
labels[printLabelsIndex].PrintLabel(ev.Graphics);
}
This code produces this print:
It is a good thing that Graphics.DrawImage honors the Bitmap's resolution, although it sometimes leads to confusion, when one assumes that all pieces of the puzzle have the same resolution..
Here you need to set the resolution of the temporary Bitmap explicitly or else if simply inherits the screen resolution..:
bmp.SetResolution(600,600)
Of course now the Labels' Size will probably not be large enough..
Also note a problem with terminology: Resolution may mean size i.e. pixels or printer dots but really ought to mean density i.e. dpi or ' dots per inch' .
You want to bring up the size and also the dpi!
Related
I have been using Bitmap to take a capture of my main form and saving it as jpeg. Unfortunately bitmap does not keep my text colour. Best way I can describe this is by images (see below). My mainform has an objectlistview which has a column coloured red. Bitmap however captures this as black text? why?
Is there any other alternative method I can use?
I have tried capturing screen and cutting out the the mainform as shown in the code below. This works great on a 1080p monitor, but not on my 4k monitor with 200% scaling, it results in the image being cut.
public void SaveControlImage(Form form)
{
string path_and_file = "C:\1.png";
Bitmap controlBitMap = new Bitmap(form.Width, form.Height);
Graphics g = Graphics.FromImage(controlBitMap);
g.CopyFromScreen(PointToScreen(form.Location), new Point(0, 0), form.Size);
// example of saving to the desktop
controlBitMap.Save(path_and_file, System.Drawing.Imaging.ImageFormat.Png);
}
I currently have a Bitmap image. I need to place this image at a certain coordinate inside a PictureBox. Specifically, I'm looking to place it 5 pixels from the top and 5 pixels from the left. The bitmap will be of different lengths, so I want the starting point to always start drawing the Bitmap at this specific point.
As an example, here are two "Bitmaps" that both start at the coordinate 5,5, with different lengths. Imagine the Gray is the PictureBox:
I've tried something like passing in a PictureBox and using graphics to draw the bitmap:
private void setQuantity(PictureBox pb, int quantity) {
Graphics g = pb.CreateGraphics();
g.DrawImage(iqc.createQuantityImage(quantity), 0, 0);
g.Dispose();
}
iqc.createQuantityImage() returns a Bitmap
But this doesn't seem to draw anything. I have also changed the x and y and nothing changes.
I'd like to be able to specify the exact coordinate or point inside the PictureBox if possible.
Thanks for any help!
You can draw image in PictureBox at any location by adding an event handler to its Paint method as follows;
private void PictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(_myBitmap, new Point(5, 5)); //Here new Point(x,y) determines location in pictureBox where you want to draw the bitmap.
}
I am working with a fingerprint module and am able to capture and display the output in a picture box (C#). Now picture.Image is null even though picturebox displays an image. So I am trying to save the picturebox image as bmp and then assign that bmp to the same picturebox so that Picturebox.image is not null.
Here is the code :
Bitmap bmp = new Bitmap(picFP.width, picFP.height);
picFP.DrawToBitmap(bmp, picFP.ClientRectangle);
bmp.Save("path", Imageformat.bmp);
picFP.image = bmp;
Here bitmap image saved is blank. What can be the problem?
A PictureBox has three layers it can display and PictureBox.DrawToBitmap will put all three things into the Bitmap:
The BackgroundImage
The Image
Any graphics created in or from the Paint event
If your bitmap comes out black then you have none of the three, or the last you have is all black.
From your description it seems as if you can display the image in the PictureBox.
So I assume that you don't display it in the right way, probably you do it like this:
using (Graphics G = picFP.CreateGraphics())
G.DrawImage(yourCapturedImage, ..)
This will not work as it only creates non-persistent graphics. These go away with e.g. each minimize-restore cycle and are not called from the DrawToBitmap call
If you really want to draw it onto the PB's surface use the Paint event! But the more natural choice would be to set the PB's Image directly:
picFP.Image = yourCapturedImage;
Update 1 As you now reveal that you don't display it yourself but simply give the control handle to the external code objNitgen=picFP.Handle; the same applies: It is that Nitgen draws only onto the surface and the result is non-persistent.
In this case the remedy is either
Taking a screenshot of the result and then work from that. Here is a post that shows you how to capture a control via screenshot..
Or you may want to check if Nitgen will draw into a bitmap directly..
For this you should be to pass it not a handle to the PictureBox but to a Bitmap instead:
private void button_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(picFP.ClientSize.Width, picFP.ClientSize.Height);
Graphics G = Graphics.FromImage(bmp);
IntPtr dc= G.GetHdc();
objNitgen = dc;
objNitgen.capture();
G.ReleaseHdc(dc);
pictureBox1.Image = bmp; // now display..
bmp.Save(yourfilename); // .. and/or save
}
Update 2
You noted in a comment that doing a manual screenshot also does not capture the image; so it seems the control handle is only used to overlay it with the image much like video overlays do; if this is the case I doubt you can get at the image without using other, more fitting Nitgen SDK methods.
In my C# program I have a Picturebox in which i want to show a stream of video (consecutive frames). I receive raw data, that I then transform into Bitmap or Image. I can show one image at a time without a problem (to reproduce the video stream).
Now my issue is that I want to merge 2 or more bitmaps (like layers) with the same size and alpha values (ARGB) and show it on the picturebox.
I have read lots of websites and posts here on SO, but many use the Graphics class, and I just can't draw it on my application (very likely because i'm new to C#! and already have my program setup, so I didn't want to change the structure).
What i need (to know):
How to overlay two or more Bitmaps with alpha values;
NO pixel manipulation please, can't afford that cost in performance.
Thank you so much in advance!
NOTE: I think this question shouldn't be marked (or closed) as duplicate, because everything i found in SO is done either with pixel manipulation or through the Graphics class. (but I might be wrong!)
EDIT: Possible workaround (NOT the solution to the question)
In
A PictureBox Problem, the 4th answer (from user comecme) tells me to have 2 picturebox, one on top of the other. The only (extra) thing I had to do to make it work with this approach was:
private void Form1_Load(object sender, EventArgs e)
{
pictureBox2.Parent = pictureBox1;
}
Where pictureBox2 will be the one on top.
I won't consider this an answer to this problem, because I consider it a workaround (specially because having more than 10 pictureboxes doesn't seem ideal! lol). That's why I will leave this question opened waiting for a real answer to my question.
EDIT: Resolved! check my answer.
Here is the real answer to my problem.
1) Use a List<Bitmap> to store all the images you want to blend;
2) Create a new Bitmap to hold the final image;
3) Draw each image on top of the final image's graphics using the using statement.
The code:
List<Bitmap> images = new List<Bitmap>();
Bitmap finalImage = new Bitmap(640, 480);
...
//For each layer, I transform the data into a Bitmap (doesn't matter what kind of
//data, in this question) and add it to the images list
for (int i = 0; i < nLayers; ++i)
{
Bitmap bitmap = new Bitmap(layerBitmapData[i]));
images.Add(bitmap);
}
using (Graphics g = Graphics.FromImage(finalImage))
{
//set background color
g.Clear(Color.Black);
//go through each image and draw it on the final image (Notice the offset; since I want to overlay the images i won't have any offset between the images in the finalImage)
int offset = 0;
foreach (Bitmap image in images)
{
g.DrawImage(image, new Rectangle(offset, 0, image.Width, image.Height));
}
}
//Draw the final image in the pictureBox
this.layersBox.Image = finalImage;
//In my case I clear the List because i run this in a cycle and the number of layers is not fixed
images.Clear();
Credits go to Brandon Cannaday in this tech.pro webpage.
This is the high level problem I'm trying to solve...
I have a 3rd party plotting/graphing (IoComp Plot), and I want to embed a high quality (at least 600 dpi) bitmap of the Plot control in reports created by another 3rd party report package (Combit List & Label).
This is the approach that seems most promising so far...
---Edit---:
After trying many other approachs, the only one that I think I can make work is to create a hidden instance of the Plot control, with everything scaled up to printer size (approx 5 times screen size). That includes width and height, font sizes, line widths - every visible component of the control. Yuck!
------
I can get a Graphics object of the proper resolution from the plot control's PrintPage event, but converting it to a Bitmap so the report package will be happy is proving to be the major stumbling block. Several hours of searching has led to other people who asked the same question, but no viable answers.
The only promising lead I've found suggested using one of the Bitmap constructors, which takes a Graphics instance as a parameter.
However, it's not working for me. It creates Bitmap, but with no content from the Plot control - it is a pure black image.
Here's my code (edited to show drawing of red line to Graphics object):
void PrintDocument_PrintPage(object sender, PrintPageEventArgs e)
{
// Draw a red line on the Graphics object. When printed, this
// line is shown as part of the normal Plot graphics.
Pen myPen;
myPen = new Pen(Color.Red);
e.Graphics.DrawLine(myPen, 0, 0, 200, 200);
myPen.Dispose();
// Create a bitmap from the Graphics object
Bitmap bm = new Bitmap(1000, 1000, e.Graphics);
// Save to disk
// DOES NOT WORK - CREATES FILE THAT IS PURE BLACK (VIEWED
// WITH "PAINT" PROGRAM)
bm.Save(#"C:\Bicw_Dev\Bic.Net\FrontEnd\GraphicsToBmp.bmp", ImageFormat.Bmp);
bm.Dispose();
}
Can anyone suggest why this doesn't work? Is this even a valid approach?
Also, please note:
As far as I can determine (and I've spent quite a bit of time looking) there is no way to get a high resolution, print quality Bitmap from the Plot control directly!
I stress this because several others who asked the question got code samples in response that solved the opposite problem - converting a Bitmap to a Graphics.
I need to convert a Graphics object to a Bitmap object.
And if anyone can suggest an alternate approach that allows me to get a print quality image of my plots into my reports, please feel free. (For example, I can get a low quality (72 bpi) Bitmap from the Plot control, and have considered trying to stretch it - but I've never seen that approach work well in other applications).
Thanks,
-Tom Bushell
Edit in response to comment:
As an experiment, I added the following:
Pen myPen;
myPen = new Pen(Color.Red);
e.Graphics.DrawLine(myPen, 0, 0, 200, 200);
myPen.Dispose();
This caused a red line to be drawn over the plot graphics when I printed my plot. But it had no effect on the Bitmap - it's still pure black.
However, it's not working for me. It
creates Bitmap, but with no content
from the Plot control - it is a pure
black image.
Well you never do paint to the graphics, what do you expect?
You are suppose to do the actual drawing for the output in that event.
The constructor you're using does not copy any graphics, only sets the resolution equal to the graphics resolution. See msdn. As Leppie points out, you have to actually draw something to the bitmap. I suggest getting another graphics object for the item you just created.
Graphics g = Graphics.FromImage(bmp);
//Make the background white
g.FillRectangle(Brushes.White, 0, 0, 1000, 1000);
It is not easy to control the DPI in the Print(Preview) system.
But maybe you are going about it the wrong way. What you want is to create a (large) bitmap and then 'trick' the control in to using that bitmap as if it was the screen. See this list of links.
No need for PrintDocument.