I have an application A that is made in WPF and WinForms.I have written another Application in WinForms for Capturing Screen. The problem I'm facing is that The dialog boxes that come up in Application A do not captured in the screen. The whole screen gets captured including the area behind the dialog box but the dialog box doesn't get captured.
public void CaptureScreen(string filepath)
{
string[] words = filepath.Split('\\');
string newFilePath = " ";
foreach (string word in words)
{
if (!(word.Contains(".bmp")))
{
newFilePath = newFilePath + word + "//";
}
else
{
newFilePath = newFilePath + word;
}
}
this.WindowState = FormWindowState.Minimized;
Screen[] screens;
screens = Screen.AllScreens;
int noofscreens = screens.Length, maxwidth = 0, maxheight = 0;
for (int i = 0; i < noofscreens; i++)
{
if (maxwidth < (screens[i].Bounds.X + screens[i].Bounds.Width)) maxwidth = screens[i].Bounds.X + screens[i].Bounds.Width;
if (maxheight < (screens[i].Bounds.Y + screens[i].Bounds.Height)) maxheight = screens[i].Bounds.Y + screens[i].Bounds.Height;
}
var width = maxwidth;
var height = maxheight;
Point sourcePoint = Point.Empty;
Point destinationPoint = Point.Empty;
Rectangle rect = new Rectangle(0, 0, width, height);
Bitmap bitmap = new Bitmap(rect.Width, rect.Height);
Graphics g = Graphics.FromImage(bitmap);
// g.CopyFromScreen(sourcePoint, destinationPoint, rect.Size);
g.CopyFromScreen(new Point(rect.Left, rect.Top), Point.Empty, rect.Size);
bitmap.Save(filepath, ImageFormat.Bmp);
//Console.WriteLine("(width, height) = ({0}, {1})", maxx - minx, maxy - miny);
}
}
}
Bitmap bmpScreenshot = new Bitmap(Screen.AllScreens[1].Bounds.Width, Screen.AllScreens[1].Bounds.Height, PixelFormat.Format32bppArgb);
Graphics.FromImage(bmpScreenshot).CopyFromScreen(
Screen.AllScreens[1].Bounds.X,
Screen.AllScreens[1].Bounds.Y,
0,
0,
Screen.AllScreens[1].Bounds.Size,
CopyPixelOperation.SourceCopy);
this.picExtendedModitorScreen.Image = bmpScreenshot;
this.picExtendedModitorScreen.Refresh();
Put this code in timer tick event.
I have put extended screen 1 in the code you can change it to any other.
Related
I've written a quick winform app that can take some entered text, generate images based on all the system fonts and then consolidate those images into a single image to give examples of the fonts. For ease, I've separated the two functions, one to generate the images and another to consolidate them so I can remove fonts I don't want in the single image. It was all working yesterday, but now when it comes to saving the consolidated image ("complete.save("consolidated.png");) it gives the useless GDI+ error. I've checked paths and access, all are fine and correct. Nothing is locking the image, so I'm totally at a loss as what is causing this. Any ideas? Code below
StringBuilder sb = new StringBuilder();
List<string> files = FileSystemUtilities.ListFiles("fonts");
int height = 0;
int width = 0;
Bitmap test = new Bitmap(1000, 1000);
Graphics gTest = Graphics.FromImage(test);
Font font = new Font("Arial", 128);
int numWidth = 0;
int count = 1;
foreach (var file in files)
{
sb.AppendFormat("{0}\r", FileSystemUtilities.GetFileName(file).Replace(".png", string.Empty));
Bitmap bitmap = new Bitmap(file);
height = height + bitmap.Height + 10;
if (width < bitmap.Width)
{
width = bitmap.Width;
}
SizeF numSize = gTest.MeasureString(Convert.ToString(count), font);
if (numWidth < numSize.Width)
{
numWidth = Convert.ToInt32(numSize.Width + 1);
}
bitmap.Dispose();
count++;
}
test.Dispose();
gTest.Dispose();
numWidth = numWidth + 10;
count = 1;
Bitmap complete = new Bitmap(width + numWidth, height);
Graphics g = Graphics.FromImage(complete);
g.FillRectangle(Brushes.White, 0, 0, complete.Width, complete.Height);
int y = 0;
foreach (var file in files)
{
Bitmap bitmap = new Bitmap(file);
g.DrawString(Convert.ToString(count) + ".", font, Brushes.Black, 0, y);
g.DrawImage(bitmap, numWidth, y);
y = y + bitmap.Height + 10;
bitmap.Dispose();
count++;
}
string filename = "consolidated.png";
if (File.Exists(filename))
{
File.Delete(filename);
}
g.Dispose();
complete.Save("consolidated.png");
complete.Dispose();
TextFileUtilities.WriteTextFile("consolidated.txt", sb.ToString());
Turns out it was due to excessive height... I couldn't see it. Thank you for all that commented and helped me out.
DrawImage method of Graphics class is not creating high quality images. In this method I am splitting a master image into multiple image but the code generating first image in very low quality. But it is generating full black images for remaining height.
public static Bitmap[] Split(byte[] ByteImage)
{
// MasterImage: there is no problem in master image. it is saving it in good quality.
MemoryStream ms = new MemoryStream(ByteImage);
System.Drawing.Image MasterImage = System.Drawing.Image.FromStream(ms);
MasterImage.Save(HttpContext.Current.Server.MapPath("../../../App_Shared/Reports/Temp/MasterImage.Bmp"), ImageFormat.Bmp);
//Split master image into multiple image according to height / 1000
Int32 ImageHeight = 1000, ImageWidth = MasterImage.Width, MasterImageHeight = MasterImage.Height;
int PageCount = 0;
Int32 TotalPages = MasterImage.Height / 1000;
Bitmap[] imgs = new Bitmap[TotalPages];
for (int y = 0; y + 1000 < MasterImageHeight; y += 1000, PageCount++)
{
imgs[PageCount] = new Bitmap(ImageWidth, ImageHeight, PixelFormat.Format32bppPArgb);
using (Graphics gr = Graphics.FromImage(imgs[PageCount]))
{
gr.CompositingQuality = CompositingQuality.HighQuality;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.SmoothingMode = SmoothingMode.HighQuality;
//First image now working with this code line
gr.DrawImage(MasterImage, new System.Drawing.Rectangle(0, y, ImageWidth, ImageHeight),new System.Drawing.Rectangle(0, 0, ImageWidth, ImageHeight), GraphicsUnit.Pixel); //new System.Drawing.Rectangle(new Point(0, y), new Size(ImageWidth, ImageHeight)));
//gr.DrawImage(MasterImage, new System.Drawing.Rectangle(0, y, ImageWidth, ImageHeight)); //new System.Drawing.Rectangle(new Point(0, y), new Size(ImageWidth, ImageHeight)));
string FilePath = HttpContext.Current.Server.MapPath("../../../App_Shared/Reports/Temp/Image" + PageCount.ToString() + ".bmp");
imgs[PageCount].Save(FilePath, System.Drawing.Imaging.ImageFormat.Bmp);
//Here it is saving images. I got first image with very poor quality but remaining in total balck color.
gr.Dispose();
}
}
return imgs;
}
As #HansPassant mentioned the source and target rectangle are reversed.
You could also change the structure of your splitting a bit so it could work a bit more flexible, and it might have a better readability at a later time.
class Program
{
static IList<Bitmap> SplitImage(Bitmap sourceBitmap, int splitHeight)
{
Size dimension = sourceBitmap.Size;
Rectangle sourceRectangle = new Rectangle(0, 0, dimension.Width, splitHeight);
Rectangle targetRectangle = new Rectangle(0, 0, dimension.Width, splitHeight);
IList<Bitmap> results = new List<Bitmap>();
while (sourceRectangle.Top < dimension.Height)
{
Bitmap pageBitmap = new Bitmap(targetRectangle.Size.Width, sourceRectangle.Bottom < dimension.Height ?
targetRectangle.Size.Height
:
dimension.Height - sourceRectangle.Top, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(pageBitmap))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
g.DrawImage(sourceBitmap, targetRectangle, sourceRectangle, GraphicsUnit.Pixel);
}
sourceRectangle.Y += sourceRectangle.Height;
results.Add(pageBitmap);
}
return results;
}
static void Main(string[] args)
{
string sourceFilename = Environment.CurrentDirectory + #"\testimage.jpg";
Bitmap sourceBitmap = (Bitmap)Image.FromFile(sourceFilename);
var images = SplitImage(sourceBitmap, 79);
int len = images.Count;
for (int x = len; --x >= 0; )
{
var bmp = images[x];
string filename = "Images-" + x + ".bmp";
bmp.Save(Environment.CurrentDirectory + #"\" + filename, ImageFormat.Bmp);
images.RemoveAt(x);
bmp.Dispose();
Console.WriteLine("Saved " + filename);
}
Console.WriteLine("Done with the resizing");
}
}
This would also dynamically size the last image in case the page is less than your specified bitmap height at the end :)
I Have windows form but i want to print panel in windows form to hidden print button and it's my code :
private void printDoc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
System.Drawing.Image image = System.Drawing.Image.FromStream(this.streamToPrint);
int x = e.MarginBounds.X;
int y = e.MarginBounds.Y;
int width = image.Width;
int height = image.Height;
if ((width / e.MarginBounds.Width) > (height / e.MarginBounds.Height))
{
width = e.MarginBounds.Width;
height = image.Height * e.MarginBounds.Width / image.Width;
}
else
{
height = e.MarginBounds.Height;
width = image.Width * e.MarginBounds.Height / image.Height;
}
System.Drawing.Rectangle destRect = new System.Drawing.Rectangle(x, y, width, height);
e.Graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, System.Drawing.GraphicsUnit.Pixel);
}
public void StartPrint(Stream streamToPrint, string streamType)
{
this.printDoc.PrintPage += new PrintPageEventHandler(printDoc_PrintPage);
this.streamToPrint = streamToPrint;
this.streamType = streamType;
System.Windows.Forms.PrintDialog PrintDialog1 = new PrintDialog();
PrintDialog1.AllowSomePages = true;
PrintDialog1.ShowHelp = true;
PrintDialog1.Document = printDoc;
DialogResult result = PrintDialog1.ShowDialog();
if (result == DialogResult.OK)
{
printDoc.Print();
//docToPrint.Print();
}
}
private void button_Print_Certificate_Click(object sender, EventArgs e)
{
Graphics g1 = this.CreateGraphics();
Image MyImage = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height, g1);
Graphics g2 = Graphics.FromImage(MyImage);
IntPtr dc1 = g1.GetHdc();
IntPtr dc2 = g2.GetHdc();
BitBlt(dc2, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height, dc1, 0, 0, 13369376);
g1.ReleaseHdc(dc1);
g2.ReleaseHdc(dc2);
MyImage.Save(#"D:\PrintPage.jpg", ImageFormat.Jpeg);
FileStream fileStream = new FileStream(#"D:\PrintPage.jpg", FileMode.Open, FileAccess.Read);
StartPrint(fileStream, "Image");
fileStream.Close();
if (System.IO.File.Exists(#"D:\PrintPage.jpg"))
{
System.IO.File.Delete(#"D:\PrintPage.jpg");
}
}
In order to print a particular control, you'll want to use that control as the source of your BitBlt operation.
So instead of this.CreateGraphics(), call panel.CreateGraphics(). Similarly, use panel.ClientRectangle to get the width and height of the image.
But take a look at https://stackoverflow.com/a/597088/103167 which gives you an easier way.
My code:
private void CreateAnimatedGif(List<string> GifsFilesRadar , List<string> GifsFilesSatellite)//string FileName1 , string FileName2)
{
Bitmap bitmap = null;
DirectoryInfo inf = new DirectoryInfo(tempGifFiles);
FileInfo[] fi = inf.GetFiles("*.gif");
for (int i = 0; i < fi.Length; i++)
{
Bitmap file1 = new Bitmap(GifsFilesRadar[i]);
Bitmap file2 = new Bitmap(GifsFilesSatellite[i]);
//calculate the new width proportionally to the new height it will have
int newWidth = file1.Width + file1.Width / (file2.Height / (file2.Height - file1.Height));
bitmap = new Bitmap(newWidth + file2.Width, Math.Max(file1.Height, file2.Height));
using (Graphics g = Graphics.FromImage(bitmap))
{
//high quality rendering and interpolation mode
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
//resize the left image
g.DrawImage(file1, new Rectangle(0, 0, newWidth, file2.Height));
g.DrawImage(file2, newWidth, 0);
string t = #"d:\GifsForAnimations" + "\\" + i.ToString("D6") + ".Gif";
bitmap.Save(t, System.Drawing.Imaging.ImageFormat.Gif);
if (i == 4)
{
break;
}
}
}
List<string> gif = new List<string>();
DirectoryInfo info = new DirectoryInfo(#"d:\GifsForAnimations");
FileInfo[] finfo = info.GetFiles();
for (int i = 0; i < finfo.Length; i++)
{
gif.Add(finfo[i].FullName);
}
newFile.MakeGIF(gif, #"d:\newGifAnim.gif", 80, true);
}
In the end I have new animated gif file.
Now I have the border and these are the locations:
Bottom left corner: 232.0,408.0
Top left corner: 232.0,211.0
Top right corner: 524.0,211.0
Bottom right corner: 524.0,408.0
I want to add on each image a frame around it to mark the border around. Let's say the border will be in Red and the border line size will be 5 pixels.
How can I create the rectangle around existing bitmap or gif file ?
It doesn't have to be connected to my example code here but how do I create the frame/border around the image with the locations I have ?
You could add this line after g.DrawImage(file2, newWidth, 0);
g.DrawRectangle(new Pen(Brushes.Red, 5), new Rectangle(0, 0, newWidth, file2.Height));
Here is a small test method so you can see it working
private void button1_Click(object sender, EventArgs e)
{
Bitmap bitmap = new Bitmap(#"C:\avatar63.jpg");
using (Graphics g = Graphics.FromImage(bitmap))
{
g.DrawRectangle(new Pen(Brushes.Red, 5), new Rectangle(0, 0, bitmap.Width, bitmap.Height));
}
bitmap.Save(#"C:\avatar63New.jpg");
}
Before: After:
You can add the rectagle anywhere you want, tou jst need to supply the X,Y,Width,Height
g.DrawRectangle(new Pen(Brushes.LimeGreen, 5), new Rectangle(50, 50, 100, 100));
Using your 4 point structure this should work
Point topLeft = new Point(232,211 );
Point topRightr = new Point(232, 408);
Point bottomLeft = new Point(524, 211);
Point bottomRight = new Point(524, 408);
g.DrawRectangle(new Pen(Brushes.LimeGreen, 5), new Rectangle(topLeft, new Size(topRightr.X - topLeft.X, bottomLeft.Y - topLeft.Y)));
// TopLeft = rectangle location
// TopRight.X - TopLeft.X = Width of rectangle
// BottomLeft.Y - TopLeft.Y = height of rectangle
So what I'm trying to do is take the Kinect Skeletal Sample and save x amount of photos, only when a human goes by. I have gotten it to work, except once it detects a human it just records x amount of photos even once the person leaves the vision of Kinect. Does anyone know how to make it so that once a person enters it starts recording, and once they leave it stops?
Variables
Runtime nui;
int totalFrames = 0;
int totalFrames2 = 0;
int lastFrames = 0;
int lastFrameWithMotion = 0;
int stopFrameNumber = 100;
DateTime lastTime = DateTime.MaxValue;
Entering/Exiting the Frame
void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
SkeletonFrame skeletonFrame = e.SkeletonFrame;
int iSkeleton = 0;
++totalFrames;
string bb1 = Convert.ToString(totalFrames);
//Uri uri1 = new Uri("C:\\Research\\Kinect\\Proposal_Skeleton\\Skeleton_Img" + bb1 + ".png");
Uri uri1 = new Uri("C:\\temp\\Skeleton_Img" + bb1 + ".png");
// string file_name_3 = "C:\\Research\\Kinect\\Proposal_Skeleton\\Skeleton_Img" + bb1 + ".png"; // xxx
Brush[] brushes = new Brush[6];
brushes[0] = new SolidColorBrush(Color.FromRgb(255, 0, 0));
brushes[1] = new SolidColorBrush(Color.FromRgb(0, 255, 0));
brushes[2] = new SolidColorBrush(Color.FromRgb(64, 255, 255));
brushes[3] = new SolidColorBrush(Color.FromRgb(255, 255, 64));
brushes[4] = new SolidColorBrush(Color.FromRgb(255, 64, 255));
brushes[5] = new SolidColorBrush(Color.FromRgb(128, 128, 255));
skeleton.Children.Clear();
//byte[] skeletonFrame32 = new byte[(int)(skeleton.Width) * (int)(skeleton.Height) * 4];
foreach (SkeletonData data in skeletonFrame.Skeletons)
{
if (SkeletonTrackingState.Tracked == data.TrackingState)
{
// Draw bones
Brush brush = brushes[iSkeleton % brushes.Length];
skeleton.Children.Add(getBodySegment(data.Joints, brush, JointID.HipCenter, JointID.Spine, JointID.ShoulderCenter, JointID.Head));
skeleton.Children.Add(getBodySegment(data.Joints, brush, JointID.ShoulderCenter, JointID.ShoulderLeft, JointID.ElbowLeft, JointID.WristLeft, JointID.HandLeft));
skeleton.Children.Add(getBodySegment(data.Joints, brush, JointID.ShoulderCenter, JointID.ShoulderRight, JointID.ElbowRight, JointID.WristRight, JointID.HandRight));
skeleton.Children.Add(getBodySegment(data.Joints, brush, JointID.HipCenter, JointID.HipLeft, JointID.KneeLeft, JointID.AnkleLeft, JointID.FootLeft));
skeleton.Children.Add(getBodySegment(data.Joints, brush, JointID.HipCenter, JointID.HipRight, JointID.KneeRight, JointID.AnkleRight, JointID.FootRight));
// Draw joints
// try to add a comment, xxx
foreach (Joint joint in data.Joints)
{
Point jointPos = getDisplayPosition(joint);
Line jointLine = new Line();
jointLine.X1 = jointPos.X - 3;
jointLine.X2 = jointLine.X1 + 6;
jointLine.Y1 = jointLine.Y2 = jointPos.Y;
jointLine.Stroke = jointColors[joint.ID];
jointLine.StrokeThickness = 6;
skeleton.Children.Add(jointLine);
}
// ExportToPng(uri1, skeleton);
// SoundPlayerAction Source = "C:/LiamScienceFair/muhaha.wav";
//SoundPlayer player1 = new SoundPlayer("muhaha.wav")
// player1.Play();
// MediaPlayer.
// axWindowsMediaPlayer1.currentPlaylist = axWindowsMediaPlayer1.mediaCollection.getByName("mediafile");
nui.VideoFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_ColorFrameReady2);
}
iSkeleton++;
} // for each skeleton
}
Actual Code
void nui_ColorFrameReady2(object sender, ImageFrameReadyEventArgs e)
{
// 32-bit per pixel, RGBA image xxx
PlanarImage Image = e.ImageFrame.Image;
int deltaFrames = totalFrames - lastFrameWithMotion;
if (totalFrames2 <= stopFrameNumber & deltaFrames > 300)
{
++totalFrames2;
string bb1 = Convert.ToString(totalFrames2);
// string file_name_3 = "C:\\Research\\Kinect\\Proposal\\Depth_Img" + bb1 + ".jpg"; xxx
string file_name_4 = "C:\\temp\\Video2_Img" + bb1 + ".jpg";
video.Source = BitmapSource.Create(
Image.Width, Image.Height, 96, 96, PixelFormats.Bgr32, null, Image.Bits, Image.Width * Image.BytesPerPixel);
BitmapSource image4 = BitmapSource.Create(
Image.Width, Image.Height, 96, 96, PixelFormats.Bgr32, null, Image.Bits, Image.Width * Image.BytesPerPixel);
image4.Save(file_name_4, Coding4Fun.Kinect.Wpf.ImageFormat.Jpeg);
if (totalFrames2 == stopFrameNumber)
{
lastFrameWithMotion = totalFrames;
stopFrameNumber += 100;
}
}
}
In most setups I have used in the skeletal tracking event area there is a check for if (skeleton != null) all you need to do is reset your trigger once a null skeleton is received.
The SDK will send a skeleton frame every time the event is fired so...
if(skeleton != null)
{
\\do image taking here
}
else
{
\\reset image counter
}
I would try something like this. Create a bool class variable named SkeletonInFrame and initialize it to false. Every time SkeletonFrameReady fires, set this bool to true. When you process a color frame, only process if this variable is true. Then after you process a color frame, set the variable to false. This should help you stop processing frame when you are no longer receiving skeleton events.