Webcam image differ from printed image - c#

I am busy with a C# winform software. I use webcam to take a picture which display in a pictureBox.
When I capture the image with the webcam, it captures a zoomed image, and when printing, it is a stretched image. I have tried a variety of SizeMode settings.All give the same result
Because I am not sure where the fault is, I will include as much detail as possible:
Using
using AForge.Video;
using AForge.Video.DirectShow;
Selecting Camera:
webcam = new FilterInfoCollection(FilterCategory.VideoInputDevice);
foreach (FilterInfo VideoCaptureDevice in webcam)
{
cmbVideoList.Items.Add(VideoCaptureDevice.Name);
}
Using camera (btn click):
cam = new VideoCaptureDevice(webcam[cmbVideoList.SelectedIndex].MonikerString);
cam.NewFrame += new NewFrameEventHandler(cam_NewFrame);
cam.Start();
if (cam.IsRunning)
{
btnStart.Hide();
}
btnStop.Show();
}
void cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Bitmap bit = (Bitmap)eventArgs.Frame.Clone();
pboxPhoto.Image = bit;
}
PictureBox size:
Width: 226
Height: 328
Printing code:
PictureBox pict = (PictureBox)pboxPhoto;
pict.SizeMode = PictureBoxSizeMode.Zoom;
e.Graphics.DrawImage(pict.Image, 20, 416, 305, 328);
Here is a sample of the image on software:
enter image description here
Sample of printed image.
enter image description here

The simplest way is to tell the PictureBox to draw itself to a Bitmap.
This can be done with all Controls and the result will include not just the Image and maybe BackgroundImage but also anything drawn in the Paint event as well as any nested Controls.
Here is a simple example:
Size sz = pictureBox1.ClientSize;
using (Bitmap bmp = new Bitmap(sz.Width, sz.Height))
{
pictureBox1.DrawToBitmap(bmp, pictureBox1.ClientRectangle);
// save the image..
bmp.Save(yourfilepath, ImageFormat.Png);
// ..or print it!
}
A few notes:
Due to the using clause the Bitmap get disposed after the last curly, so you would either make use of it inside scope or change to a pattern that disposes of the Bitmap at a later point in time.
The nested Controls will be drawn a reverse order which will cause problem if they are overlapping!
Only nested, not overlayed Controls will be included. Since PictureBox is not a Container (as opposed to e.g. a Panel) it won't do to simply placea, say Label, over it; instead you need to nest it in code, i.e. make the PictureBox its Parent and also set a suitable relative Location..
By default the Bitmap will have the current machine's screen dpi resolution. You cold change it afterwards with bmp.SetResolution()..

Related

Saving all content of RichTextBox as a bitmap

I have a RichTextBox that is a letterbox view of a long set of data. This means I have the vertical scroll bar to move what I see up and down. What I am trying to do is save the whole data as a bitmap even that not visible in the control. I can save the control as a bitmap but that is only part of the data.
Code to save control is borrowed from someone else which does indeed save the control view (thanks to whoever wrote it):
private void btn_SaveBitmap_Click(object sender, EventArgs e)
{
SaveControlToBitmap(rchtxtbx_braille, "MyBitmap.bmp");
}
public void SaveControlToBitmap(Control control, string fileName)
{
//Get graphics from the control
Graphics g = control.CreateGraphics();
Bitmap bitmap = new Bitmap(control.Width, control.Height);
control.DrawToBitmap(bitmap, new Rectangle(0, 0, control.Width, control.Height));
bitmap.Save(fileName);
bitmap.Dispose();
}
This bitmap does not contain the data that is not visible in the control. I think somehow I need to find the start of the data and the end and turn that into a bitmap rather than turning the control itself into a bitmap but I am probably wrong. How can I do this please?
I have my laptops display set to 125% and this in itself may cause some issue. Please ask if this is not clear and I will try explain different way.

Custom bitmap capture that keeps formatting?

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);
}

Convert PictureBox image to 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.

Paste the contents of a Bitmap into a PictureBox

I'm currently writing a little paint application where the user is able to draw on a Panel. I am working on the select tool and want to be able to select a certain area of the Panel, and then paste this selected area directly into a PictureBox that I have just to the right of the Panel.
My problem is that my code at the moment is not working correctly, when I try to paste the Bitmap that I am creating from the panel I am getting a big red X in the PictureBox instead of the actual image. I know that the image is copying to the Bitmap correctly because I tried putting some code around it to save it to disk as a jpeg and then look at the image, and it is all displaying fine.
Here is my code:
private void tbCopy_Click(object sender, EventArgs e)
{
int width = selectList[0].getEnd().X - selectList[0].getInitial().X;
int height = selectList[0].getEnd().Y - selectList[0].getInitial().Y;
using (Bitmap bmp = new Bitmap(width, height))
{
pnlDraw.DrawToBitmap(bmp, new System.Drawing.Rectangle(
selectList[0].getInitial().X,
selectList[0].getInitial().Y,
width, height));
pbPasteBox.Image = bmp;
}
}
the width and height are just the dimensions of the area that I want to copy, and selectList is a List that contains one object which contains the coordinates of the area I want to copy.
Any help would be greatly appreciated.
Your problem is the using(){} when the code inside the using braces has completed the object inside the () is disposed of as it is deemed no longer needed.
Simply removing the brace to just have Bitmap bmp = new Bitmap(width, height) should solve your problem

Overlay two or more Bitmaps to show in Picturebox (C#)

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.

Categories