Custom bitmap capture that keeps formatting? - c#

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

Related

C#, Preventing erasing strokes from erasing portions of overlapped background image

I am using a C# console application project to generate raster frames and then uses
ffmpeg tool to generate the video from those frames. I am using a graphical object g to draw a bmp object and save it to
generate
the frame(s) [The rate of saving is 25 frame per second]. I implemented drawing[writing] on the graphical object fine, erasing
"ON WHITE BACKGROUND", clearing the graphical object very well,
undoing drawn shapes perfectly. 4) I attempted to set background and
import images and that worked so very well as you can write on the
graphical object [whether white paper, background image, imported
image...etc]
The problem that when I attempt to erase portion of the image which has a background [background image, for example lines,
graphical, coordinates..etc]. the graphical object erases the
portion of the image where the stroke of the erase [white color
overlaps]. Sure This [white colors for erasing strokes ] was working
fine with white page background.
I am kind of thinking out loud, logically an it makes perfect sense that the white stroke erasers will mark on the non-white
backgrounds [so it looks as the eraser erased the background].
Is there (a) way(s), mechanism, overlay algorithm, coloring mechanism :) to make show the background image parts under the erasing-strokes' points as it is, non distorted. For example,:
1) Placing the background image on the first layer
2) Perform the drawing on the top layer
3) When erasing [on the top layer], use a transparent color, or stroke mechanism to show the background image-portions' that was/were overlapped before with the background......Is that possible??
Thanks for your help and input in advance.
Note that you may not have the perfect solution. But your thoughts are appreciated.
Resolution:
Masking the original image (source image with all my shapes' drawing) and drawing it on a different destination bmp:
public static Image CropToPath(Image srcImage, List<Point> Points, Pen p, Bitmap bmp)
{
Bitmap mask = bmp;//new Bitmap(Bitmap.FromFile( (new DirectoryInfo(outPutPath)).GetFiles()?.OrderByDescending( f => f.CreationTimeUtc).First()?.FullName));
DrawPoints(Graphics.FromImage(mask), p, Points);
using (var imgattr = new ImageAttributes())
{
// set color key to Line
imgattr.SetColorKey(Color.Gainsboro, Color.Gainsboro);
// Draw non-line portions of mask onto original
using (var g3 = Graphics.FromImage(srcImage))
{
SmoothGraphic(g3).DrawImage(
mask,
new Rectangle(0, 0, srcImage.Width, srcImage.Height),
0, 0, srcImage.Width, srcImage.Height,
GraphicsUnit.Pixel, imgattr
);
return srcImage;
}
}
}

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.

Make overlapping picturebox transparent in C#.net

I have two overlapping pictureboxes.The images of both picture boxes have some transparent pixels.I want to see the bottom picture box through the transparent pixels of the overlapping picture box.
I tried setting the background color of both picture boxes as transparent.But it just sets the back color of the picture box to the background color of the form.
Clearly you are using Winforms. Yes, transparency is simulated by drawing the pixels of the Parent. Which is the form, you only see the form pixels, stacking effects don't work. There's a KB article that shows a workaround for this. It is painful. Another approach is to not use PictureBox controls but just draw the images in the form's Paint event.
Consider WPF, it has a very different rendering model that easily supports transparency.
Solutions to that problem might be various, and it mainly depends on your skills and amount of work will depend on kind of images you're dealing with. For example if images are always same resolution, size and overlapping image supports transparency you could try to do manipulation of two Image objects and draw one over another, then display it in PictureBox. Or if you will need to do it multiple times in various places of your app you could even consider creating your own UserContriol.
Code in answer of this question, method ResizeImagein particular, show how to create resized, good quality image, all you need it is to change it a little. Make it to get two Images as input parameters, and change it to draw one image over another.
Changes might look like this
public static Bitmap CombineAndResizeTwoImages(Image image1, Image image2, int width, int height)
{
//a holder for the result
Bitmap result = new Bitmap(width, height);
//use a graphics object to draw the resized image into the bitmap
using (Graphics graphics = Graphics.FromImage(result))
{
//set the resize quality modes to high quality
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//draw the images into the target bitmap
graphics.DrawImage(image1, 0, 0, result.Width, result.Height);
graphics.DrawImage(image2, 0, 0, result.Width, result.Height);
}
//return the resulting bitmap
return result;
}
And use it, for example, like this:
pictureBox1.Image = CombineAndResizeTwoImages(Image.FromFile("c:\\a.png"), Image.FromFile("c:\\b.png"), 100,100);
But that its only example, and you must tune it up to your needs.
Good luck.
If it's one PictureBox inside another, you can use:
innerPictureBox.SendToBack();
innerPictureBox.Parent = outerPictureBox;

How to export Image of my form c#

I need a solution how could i make a Print Screen of my WinForm on C# and export it as PNG.
Bests
I think this blog post will help.
using (Bitmap bitmap = new Bitmap(ParentForm.Size.Width, ParentForm.Size.Height))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(new Point(ParentForm.DesktopLocation.X, ParentForm.DesktopLocation.Y), new Point(0, 0), ParentForm.Size);
}
bitmap.Save(#"C:\test.jpg", ImageFormat.Jpeg);
}
Never tried it, but i'd think you should be able to call OnPaint(args) with a PaintEventArgs you create, that includes a Graphics for the image you want to draw on, and the ClipRectangle encompassing the whole area of the form.
This would only work if your form properly processes paint messages (ie: if it stores enough info to be able to repaint the window fully at will), and it may only get the client area (ie: it might not get the title bar or menus).

How to render images in real-time

I am looking for a solution\software that I can use in order to render buttons in real time.
That is, I have an image and text, and I want them to be an image altogether in realtime.
Thank you
You can dynamically create an image based on text using the System.Drawing namespace.
private Bitmap CreateBitmapImage(string imageText, string imageUrl)
{
Bitmap myBitmap = new Bitmap(imageUrl);
Graphics g = Graphics.FromImage(myBitmap);
g.DrawString(imageText, new Font("Tahoma", 40), Brushes.White, new PointF(0, 0));
return (objBmpImage);
}
Once you have the Bitmap object in memory you can save it to the disk and call it's location from the web.
Bitmap bmp = CreateBitmapImage("my picture", #"C:\myBasePic.bmp");
bmp.Save(#"C:\bla.png", System.Drawing.Imaging.ImageFormat.png);
It would be good if you can specify why such requirement is there. One of such scenario that I had encountered was need of image buttons with different text (round corners with shaded background) - this can easily be achieved using CSS. If you really want to combine an image and text together then you can do that at server side (using say System.Drawing types) and serve the combined image over a handler/web-service.

Categories