C# Screenshot flip flop not working - c#

I am trying to do something very specific here; Essentially, what this code does:
else if (cmd == "streams")
{
Console.WriteLine("Hello, thank you for testing out the streams beta.\nBefore you start, there are some things you should know.\n First off, all screenshots are saved to your documents folder. They are named streams and streams_green.\nTo stop recording, close the software.");
Console.WriteLine("Please enter your monitors resolution (RECORD WITH YOUR GAME IN FULLSCREEN WINDOWED)");
Console.WriteLine("X:");
int xres = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Y:");
int yres = Convert.ToInt32(Console.ReadLine());
p.Send(maxfps);
Console.WriteLine("Thank you, recording now started.");
Bitmap memoryImage;
memoryImage = new Bitmap(xres, yres);
Size s = new Size(memoryImage.Width, memoryImage.Height);
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
for (var i = 0; ; i++)
{
memoryGraphics.CopyFromScreen(0, 0, 0, 0, s);
string str = "";
string str2 = "";
str = string.Format(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) +
$#"\streams{i}.png");
str2 = string.Format(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) +
$#"\streams_green{i}.png");
System.Threading.Thread.Sleep(2);
//Send spacebar would go here
p.Send(green);
memoryImage.Save(str);
System.Threading.Thread.Sleep(1);
p.Send(regular);
memoryImage.Save(str2);
System.Threading.Thread.Sleep(1);
}
Is send a dvar to a game, take a screenshot, and another dvar, then take another screenshot ect. As you can see by "p.Send(green)" and (regular). However, I have an issue. I am trying to have this save all of the greenscreen screenshots as streams_green, and the regular ones under streams. It is currently properly saving all of the files, however, the _green images are identical to the regular ones, even though the moment the green screenshot was taken was a completely different displayed frame as the one before it. Thanks.

Based on the code your method takes only one screenshoot at line memoryGraphics.CopyFromScreen(0, 0, 0, 0, s); and then save it in two separate files by memoryImage.Save. If instancegreen (in line p.Send(green)) and instance regular (in line p.Send(regular)) have information you want to save then you should change them to Bitmap and save.

Related

How can I create a video file from separate images on a c# project

I would like to create a video file from a list in c# which can be in any format that media player can open.
I have tried Aforge and Avi file wrapper, but unfortunately they only work in x86 and I have quite a lot of dependencies so that I can not change the project type. So, it has to be x64.
All my Bitmaps are in a list (which is around 50 or so)
public List tv_ImageData = new List();
I am new to c# and don't know my way around much. I have googled and could find no solution. I'd be grateful if someone can point me to the right direction (or library).
(I feel like this would be better as a comment, but I don't have the reputation for that yet. I'm sorry if this is bad practice!)
Since your only problem with AForge seems to be that it is compiled for x86, I'll mention that it looks like you can recompile it yourself for an x64 target.
https://github.com/andrewkirillov/AForge.NET
A quick search found this link to a recompile of AForge that includes a 64-bit version:
https://archive.codeplex.com/?p=aforgeffmpeg
I wouldn't know if that's up to date or not, so I might recommend compiling it yourself.
I hope that helps!
After some mingling with SharpAvi I solved my problem.
I had a List called
List<ushort[]> tv_data = new List<ushort> tv_data();
which contained the frames as raw data (values in 0-255 range).
I tried to use the example supplied by the documentation but it gave me an upside avi(I guess its because SharpAvi expects DIB bitmaps). So I changed it a bit and borrowed a bit from here (How to create bitmap from byte array?) top get a working solution.
Here is my function:
using SharpAvi;
using SharpAvi.Output;
This may not be the best way to do it but it works. Hope someone will find it useful.
private void SaveAsVideo(object sender, RoutedEventArgs e)
{
if (loadedFileName != "")
{
try
{
var writer = new AviWriter(string.Format("{0}.avi", fullPath))
{
FramesPerSecond = (decimal)VI.FrameRate,
EmitIndex1 = true
};
var stream = writer.AddVideoStream();
stream.Width = (int)VI.VideoWidth;
stream.Height = (int)VI.VideoHeight;
stream.Codec = KnownFourCCs.Codecs.Uncompressed;
stream.BitsPerPixel = BitsPerPixel.Bpp8;
var frameData = new byte[stream.Width * stream.Height];
int frameNo = 0;
foreach (ushort[] data in tv_Data)
{
byte[] byteData = tv_Data.ElementAt(frameNo);
byte[] newbytes = PadLines(byteData, stream.Height, stream.Width);
stream.WriteFrame(true, newbytes, 0, frameData.Length);
frameNo++;
}
writer.Close();
MessageBox.Show("Video file saved.");
}
catch (Exception ex)
{
MessageBox.Show(string.Format("Failed to save video. \n {0}", ex.Message));
}
}
}
static byte[] PadLines(byte[] bytes, int rows, int columns)
{
int currentStride = columns;
int newStride = columns;
byte[] newBytes = new byte[newStride * rows];
byte[] tempBytes = new byte[newStride];
for (int i = 0; i < rows; i++)
{
Buffer.BlockCopy(bytes, currentStride * i, tempBytes, 0, currentStride);
Array.Reverse(tempBytes);
Buffer.BlockCopy(tempBytes, 0, newBytes, newStride * i, currentStride);
}
Array.Reverse(newBytes);
return newBytes;
}

Hash files are different after taking same screen shot with Selenium

I'm trying to learn about automated tests, using Selenium. I'm working alone, and so only have the docs, Google and then you guys.
Using Selenium in VS-2105, I save a screen shot of my website as an image to a file location, and then stop debugging at that point. This file then becomes the 'expected' result.
I then comment that line out, run it again, taking a screen shot but saving to a different location. The files, although of the same size, have different hash values.
To my eyes they are identical.
Is there something wrong with my approach?
This is the code which I run to create my 'master'
_webDriver.Navigate().GoToUrl(url);
var accept = _webDriver.SwitchTo().Alert();
accept.Accept();
IWebElement menu = _webDriver.FindElement(By.Id("link"));
menu.Click();
System.Threading.Thread.Sleep(500);
var screenshot = _webDriver.GetScreenshot();
var fileName = "expandMenuInPlan.png";
var origFile = _testImagesPersistentPath + fileName;
screenshot.SaveAsFile(origFile, OpenQA.Selenium.ScreenshotImageFormat.Png);
And this is the code I use to compare
_webDriver.Navigate().GoToUrl(url);
var accept = _webDriver.SwitchTo().Alert();
accept.Accept();
IWebElement menu = _webDriver.FindElement(By.Id("link"));
menu.Click();
System.Threading.Thread.Sleep(500);
var screenshot = _webDriver.GetScreenshot();
var fileName = "expandMenuInPlan.png";
var origFile = _testImagesPersistentPath + fileName;
//screenshot.SaveAsFile(origFile, OpenQA.Selenium.ScreenshotImageFormat.Png); COMMENTED OUT
//The above is identical
var newFile = _testImagesTempForTestRunPath + fileName;
screenshot.SaveAsFile(newFile, OpenQA.Selenium.ScreenshotImageFormat.Png);
string hashOrig = GetBytes(origFile);
string hashNew = GetBytes(newFile);
if (hashOrig != hashNew)
{
SaveFailedImage(origFile, newFile, fileName);
}
And the GetBytes method
private string GetBytes(string file)
{
using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
{
var img = new Bitmap(file);
ImageConverter converter = new ImageConverter();
var bytes = (byte[])converter.ConvertTo(img, typeof(byte[]));
return Convert.ToBase64String(sha1.ComputeHash(bytes));
}
}
Is using screenshots in this manner just not reliable or is there something wrong with my code?
Hashing a image file and comparing is never the right approach. Even a single pixel off will change the hash. So you don't want to to make your tests brittle
You can use the C# method ImageComparer.Compare Method (Image, Image, ColorDifference, Image)
https://msdn.microsoft.com/en-in/library/hh191601.aspx?f=255&MSPPError=-2147217396
Or you can use external tools like https://applitools.com/ which allow you to do compare images which are smart in nature
PS: I have no association with applitools and it is just one example, there might be other services available as well.

C# Real time waveform data plot using NAudio

I am new on processing wav file and C#.My goal is to real time data plotting in waveform of wavfile.I mean while recording sound(wav) file,i want to plot its graph simultaneously.I searched some sound libiraries and decide to use NAudio.(Dont know it is the best choice for me.I am open to any suggestions about choosing audio libirary). However i have no idea about real time data plotting using sound. Some people suggest GDI but as i said i am new and i think it will take too much time to use GDI efficiently.If i must learn GDI,pls share any article that can help a beginner like me. Actually i look like dont know where should i start. Need to be guided :)) And i have a question.
One of the tutorial of NAudio,he works with byte array to plot the waveform in Chart.It is fine if you know the size of wav file.However it works too slow and gives Out of Memory Exception for bigger wav files than 10mb.The code below refers to what i mean.
OpenFileDialog open = new OpenFileDialog();
open.Filter = "Wave File (*.wav)|*.wav;";
if (open.ShowDialog() != DialogResult.OK) return;
chart1.Series.Add("wave");
chart1.Series["wave"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine;
chart1.Series["wave"].ChartArea = "ChartArea1";
NAudio.Wave.WaveChannel32 wave = new NAudio.Wave.WaveChannel32(new NAudio.Wave.WaveFileReader(open.FileName));
byte[] buffer = new byte[426565];
int read;
while (wave.Position < wave.Length)
{
read = wave.Read(buffer, 0, 426565);
for (int i = 0; i < read / 4; i++)
{
chart1.Series["wave"].Points.Add(BitConverter.ToSingle(buffer, i * 4));
}
}
Is there a way to perform this operation faster?
If you plot every single sample, you will end up with a waveform that is unmanageably large since audio usually contains many thousands of samples per second. A common way waveforms are drawn is by selecting the maximum value over a period of time, and then drawing a vertical line to represent it. For example, if you had a three minute song, and wanted a waveform around 600 pixels wide, each pixel would represent about a third of a second. So you'd find the largest sample value in that third of a second and use that to plot your waveform.
Also, in your sample code you are reading an odd number of bytes. But since this is floating point audio, you should always read in multiples of four bytes.
This worked for me
WaveChannel32 wave = new WaveChannel32(new WaveFileReader(txtWave.Text));
int sampleSize = 1024;
var bufferSize = 16384 * sampleSize;
var buffer = new byte[bufferSize];
int read = 0;
chart.Series.Add("wave");
chart.Series["wave"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine;
chart.Series["wave"].ChartArea = "ChartArea1";
while (wave.Position < wave.Length)
{
read = wave.Read(buffer, 0, bufferSize);
for (int i = 0; i < read / sampleSize; i++)
{
var point = BitConverter.ToSingle(buffer, i * sampleSize);
chart.Series["wave"].Points.Add(point);
}
}

LEADTOOLS adding QRBarcode to an existing image

My current code writes a qr code but it over writes my file with just the qr code. I am not sure how to adjust the size of the qr code to be placed in one corner of the document rather than taking up the whole page. Also not sure if the RasterImage.Create means that it creates a new file with just the qr and discard my original file?
Code: - Convert PDF to Bmp to add QR then saving back to PDF
public void PDFFileExample()
{
RasterCodecs codecs1 = new RasterCodecs();
codecs1.Options.Pdf.InitialPath = #"C:\LEADTOOLS 18\Bin\Dotnet4\Win32";
codecs1.Dispose();
RasterCodecs codecs2 = new RasterCodecs();
codecs2.ThrowExceptionsOnInvalidImages = true;
System.Diagnostics.Debug.Assert(codecs2.Options.Pdf.InitialPath == #"C:\LEADTOOLS 18\Bin\Dotnet4\Win32");
string pdfFile = #"C:\QRCodeTesting\bottomRight.pdf";
string destFileName1 = #"C:\QRCodeTesting\bottomRightOutputTemp.pdf";
string destFileName2 = #"C:\QRCodeTesting\bottomRightOutput.bmp";
RasterCodecs codecs = new RasterCodecs();
if (codecs.Options.Pdf.IsEngineInstalled)
{
// Resulting image pixel depth.
codecs.Options.Pdf.Load.DisplayDepth = 24;
codecs.Options.Pdf.Load.GraphicsAlpha = 4;
codecs.Options.Pdf.Load.Password = "";
// Type of font anti-aliasing to use.
codecs.Options.Pdf.Load.TextAlpha = 1;
codecs.Options.Pdf.Load.UseLibFonts = true;
// Horizontal,vertical display resolution in dots per inch.
codecs.Options.RasterizeDocument.Load.XResolution = 150;
codecs.Options.RasterizeDocument.Load.YResolution = 150;
using (RasterImage image = codecs.Load(pdfFile, 0, CodecsLoadByteOrder.BgrOrGray, 1, 1))
{
// Set the PDF version to be v1.4
codecs.Options.Pdf.Save.Version = CodecsRasterPdfVersion.V14;
try
{
// Save the image back as PDF
codecs.Save(image, destFileName1, RasterImageFormat.RasPdf, 24);
}
catch (RasterException ex)
{
if (ex.Code == RasterExceptionCode.FileFormat)
MessageBox.Show(string.Format("Image in file {0} is loaded", destFileName1));
else
{
MessageBox.Show(string.Format("Could not load the file {0}.{1}{2}", destFileName1, Environment.NewLine, ex.Message));
}
}
}
// And load it back before saving it as BMP
using (RasterImage image = codecs.Load(destFileName1))
{
codecs.Save(image, destFileName2, RasterImageFormat.Bmp, image.BitsPerPixel);
writeQRTag(destFileName2);
}
}
else
{
MessageBox.Show("PDF Engine is not found!");
}
// Clean up
codecs.Dispose();
}
QRCode writing Method
private void writeQRTag(string imageFileName)
{
BarcodeEngine engine = new BarcodeEngine();
// Create the image to write the barcodes to
int resolution = 300;
using (RasterImage image = RasterImage.Create((int)(8.5 * resolution), (int)(11.0 * resolution), 1, resolution, RasterColor.FromKnownColor(RasterKnownColor.Red)))
{
// Write two QR barcodes
WriteQRCode(engine.Writer, image, QRBarcodeSymbolModel.Model1AutoSize, "QR Data 1", true);
// Save the image
using (RasterCodecs codecs = new RasterCodecs())
{
codecs.Save(image, imageFileName, RasterImageFormat.CcittGroup4, 1);
}
}
}
This is Maen from LEADTOOLS support.
I checked your code and noticed the following:
1) When you call RasterImage.Create() method, it will create a new RasterImage object that contains an empty red image, which you subsequently pass to the writeQRTag() function then save using the given file name.
When you save it, the red color is replaced by black because the file format you used only supports black and white. Since you're using a new image, the old image is lost (overwritten).
If you want to write the barcode on the image from the original file, you should NOT create a new image. Instead, you need to use the image you already loaded using codecs.Load() and write the barcode on it.
2) The code performs multiple load and save operations. Normally, you don't need to do that unless your application needs the different file formats (PDF, BMP and TIFF).
3) You create different instances of our RasterCodecs object but actually use only one of them. There's no need for 3 of the 4 RasterCodecs objects in the code.
If you still face problems with the code that uses our toolkit, you can send us the details in an email to support#leadtools.com and we will try to help you.

AVIStreamSetFormat error

I'm trying to create a Desktop Recording Application. When I record the full screen, the program works as it is supposed to, but in some cases when I select a specific region from the desktop to record I get an error at: int result = AVIStreamSetFormat(psCompress, 0, ref bi, (Int32)bi.biSize);
Error in VideoStreamSetFormat: -2147205016.
I'm using Xvid MPEG-4 Codec to create AVI video. I think the problem might me that Xvid MPEG-4 Codec does not accept certaint image sizes (width and height). I'm not sure and stuck on this problem and I'm asking if somebody can help me understand why it is not working.
private void SetFormat(IntPtr psCompress)
{
BITMAPINFOHEADER bi = new BITMAPINFOHEADER();
bi.biSize = (uint)Marshal.SizeOf(bi);
bi.biWidth = (Int32)_width;
bi.biHeight = (Int32)_height;
bi.biPlanes = 1;
bi.biBitCount = 24;
bi.biCompression = 0; // 0 = BI_RGB
bi.biSizeImage = _stride * _height;
int result = AVIStreamSetFormat(psCompress, 0, ref bi, (Int32)bi.biSize);
if (result != 0)
{
throw new Exception("Error in VideoStreamSetFormat: " + result.ToString());
}
}
I found what was the problem. When taking screenshots from selected regions on the desktop I had to be sure that the height and width are divisible to 2. It seems that Xvid MPEG-4 Codec does not accept just any image size.
I had the same problem.
In my case I was setting the scale and rate to 0.
Make sure you are specifying the speed of the avi correctly before calling that function.

Categories