Picturebox from AForge FFMPEG empty - C#/WinForms - c#

I've done a ton of research and looked at a lot of questions here but can't seem to find anything to help me. I should preface I'm very new to C#, Windows Forms, and SO! I'm a 1st year CompSci student coming from C++ experimenting with my own projects for the summer. I'm trying to display a series of bitmaps from a .avi using the AForge.Video.FFMPEG video file reader.
It seems to be finding the file, getting its' data (console prints dimensions, framerate, and codec) and creating the picturebox, but the picturebox comes up blank/empty. I get the bitmap from the frames of a .avi:
From AForge example code here
Then I'm trying to display it with a picture box:
From MS example code here as well
And here's my code. Essentially a combination of the two:
public class Simple : Form
{
Bitmap videoFrame;
public Simple()
{
try
{
// create instance of video reader
VideoFileReader reader = new VideoFileReader();
// open video file
reader.Open(#"C:\Users\User\Desktop\ScanTest3.AVI");
// check some of its attributes
Console.WriteLine("width: " + reader.Width);
Console.WriteLine("height: " + reader.Height);
Console.WriteLine("fps: " + reader.FrameRate);
Console.WriteLine("codec: " + reader.CodecName);
PictureBox pictureBox1 = new PictureBox();
// read 100 video frames out of it
for (int i = 0; i < 100; i++)
{
videoFrame = reader.ReadVideoFrame();
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.ClientSize = new Size(videoFrame.Width, videoFrame.Height);
pictureBox1.Image = videoFrame;
// dispose the frame when it is no longer required
videoFrame.Dispose();
}
reader.Close();
}
catch
{
Console.WriteLine("Nope");
}
}
}
class MApplication
{
public static void Main()
{
Application.Run(new Simple());
}
}
So that's it pretty much. Just a blank picture box coming up, when it should have the first frame of the video, even though no exception caught (though I'm pretty confident I'm using the try/catch very poorly), and the console printing the correct data for the file:
width: 720
height: 480
fps: 29
codec: dvvideo
[swscaler # 05E10060] Warning: data is not aligned! This can lead to a speedloss
Though if anyone could tell me what that warning means, that would be great as well, but I'm mainly just lost as to why there's no picture printing to the screen.
Thanks!

Found This post, where he uses timers to update, and it works perfectly. I'm guessing pictureBox only really works in a function maybe, not sure. Still learning. Thanks!

Related

WriteVideoFrame() with Videocodec.Raw change pixel value

I'm using Accord.Video.ffmpeg to record a video in c#. It is actually a depth video with pixels indicating the depth magnitude. From depth array I create a bitmap and the save the bitmap with WriteVideoFrame method.
Afterward, I open the video in Matlab reading frame by frame. The problem is that I have differences between the bitmap in c# and the frame in Matlab?! The difference is more or less of 10 (in a range of 255 it's a big deal)(testing at the moment if it's constant).
Since from the bitmap to videoframe I do not perform any operation I think that the problem is in the video encoder. Is is possible even though the format is Raw?!
Hints?
Alex
UPDATE
If I run this code in a new project everything is fine
unsafe private void Button_Click_1(object sender, RoutedEventArgs e)
{
writerdepth.Open("testvideo.avi", 512, 424, 15, VideoCodec.Raw);
for (int i = 0; i <depthPixels.Length; i++)
{
this.depthPixels[i] = (byte)100;
}
try
{
fixed (byte* p = depthPixels)
{
IntPtr unmanagedPointer = (IntPtr)p;
depthbm = new Bitmap(512, 424, 512, System.Drawing.Imaging.PixelFormat.Format8bppIndexed, unmanagedPointer);
}
}
catch (Exception ex)
{
Debug.WriteLine("Errore");
}
writerdepth.WriteVideoFrame(depthbm);
writerdepth.Close();
}
}
going back to my code when I try to read the image instead of RGB = [100 100 100] I have [96 94 99].
My starting code is saving depth image from kinect v2, the function is called when a new valid frame arrives.
I have no idea of the reason for this difference...
Solved... was the Nuget package I had version 3.4.2-alpha in the older project (strange behavior) and new 3.5.0 is the last one (working). Updating the package solved the problem

How can we capture and save in local disk with Aforge video?

I want to save video which capturing from webcam into local disk. I wrote code it shows webcam but It can't save into local disk. The error is Failed creating compressed stream.. What should I do in here?
writer = new AVIWriter("wmv3");
writer.FrameRate = 30;
writer.Open("video.avi", Convert.ToInt32(640), Convert.ToInt32(480)); // ERROR İS HERE **Failed creating compressed stream.**
//Create NewFrame event handler
//(This one triggers every time a new frame/image is captured
videoSource.NewFrame += new AForge.Video.NewFrameEventHandler(videoSource_NewFrame);
//Start recording
videoSource.Start();
}
}
void videoSource_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
{
//Cast the frame as Bitmap object and don't forget to use ".Clone()" otherwise
//you'll probably get access violation exceptions
pictureBoxVideo.BackgroundImage = (Bitmap)eventArgs.Frame.Clone();
writer.AddFrame((Bitmap)eventArgs.Frame.Clone());
}
Have you ever consider the size of the stream of your webcam? I have the same problem, too. I know you set your video size into 640 and 480, but the video stream size which comes from your webcam(I guess) would be never the same. I also guess you set your container such as picturebox or imagebox into 640 and 480, but that doesn't mean the video stream would be the same. I use savedialog to check the video stream that comes out of my webcam, and guess what? The size would be (648, 486). Who would ever set such a strange number set? But I set my code into this :
writer.Open("video.avi", Convert.ToInt32(648), Convert.ToInt32(486));
And it works fine!
I do not know the rest of your code is correct or not, but I'm sure my bug is in the set of size :)
Four years later I'm having this same issue. After hours I figured out if I didn't specify wmv3 for the codec and just left it blank writer = new AVIWriter(); then everything worked.
AVIWriter write = new AVIWriter();
write.Open("newTestVideo.avi", Convert.ToInt32(320), Convert.ToInt32(240));
Bitmap bit = new Bitmap(320, 240);
for (int tt = 0; tt < 240; tt++) {
bit.SetPixel(tt, tt, System.Drawing.Color.FromArgb((int)(UnityEngine.Random.value * 255f), (int)(UnityEngine.Random.value * 255f), (int)(UnityEngine.Random.value * 255f)));
write.AddFrame(bit);
}
write.Close();

Picturebox getting big red X but I can't detect or fix it

I am currently working with AForge, and have an on new frame event that posts the frame, as a bitmap, into a picturebox. 90% of the time it works great... UNLESS I fiddle with something on the winform. Changing a combo box, moving the window, or anything like that risks causing the Picturebox to switch from the video to a big red X. Code sample below:
private void connectButton_Click(object sender, EventArgs e)
{
try
{
cam = new VideoCaptureDevice(captureDevices[CameraSelectComboBox.SelectedIndex].MonikerString);
cam.NewFrame -= Handle_New_Frame; //Just to avoid the possibility of a second event handler being put on
cam.NewFrame += new AForge.Video.NewFrameEventHandler(Handle_New_Frame);
cam.Start();
}
catch
{
MessageBox.Show("An error has occured with connecting to the specified webcam. The application will now close!");
Application.Exit();
}
}
private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
try
{
if (bitmap != null)
bitmap.Dispose(); //Without this, memory goes nuts
bitmap = new Bitmap(eventArgs.Frame);
}
catch { }
//Draw some stuff on the images
bitmap = AdjustBrightness(bitmap, brightnessMeter);
bitmap = ApplyContrast(contrastMeter, bitmap);
bitmap = Draw_Top_Line(bitmap);
bitmap = Draw_Bottom_Line(bitmap);
//Set the image into the picturebox
this.Invoke((MethodInvoker)delegate
{
videoPictureBox1.Image = bitmap;
frameRate++; //Keep track of the frame rate
});
GC.Collect(); //Without this, memory goes nuts
this.Invoke((MethodInvoker)delegate {
videoPictureBox1.Refresh(); //NOT NECESSARY. JUST TRYING TO FIX THE BIG RED X!
});
if (videoPictureBox1.Image == videoPictureBox1.ErrorImage)
{
cam.Stop(); //ALSO NOT NECESSARY> AGAIN, JUST TRYING TO FIX THE BIG RED X!
cam.Start();
}
}
I put a break on the if (videoPictureBox1.Image == videoPictureBox1.ErrorImage) and it is evaluating to false, even when the big red X is up, because the image is actually being set to the bitmap. So cam.Stop() and cam.Start() never run (not sure if that would even help, but I figured I would give it a try).
videoPictureBox1.Refresh() is running every time, but again- it's not making a difference. Still have the big red X.
As I said before: if I start the video and touch nothing, the big red X will never happen. But the moment I start changing combo boxes, or dragging the form itself around, the chance of the big red X goes up exponentially. Sometimes I can flip through the combo box 10-12 times before it happens, other times it happens the second I click the combobox. :-\
Can anyone explain what is happening here and perhaps offer a suggestion on the best method to go about fixing it? I'm still very new to threading, so I've been struggling to wrap my head around exactly what is happening here and the best way to fix the issue! Any nudges in the right direction would be a huge help!
In the end, I wrapped EVERYTHING in in the Handle_New_Frame in an invoke. It completely removed the big red X issue, permanently. >_>
private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
this.Invoke((MethodInvoker)delegate
{
try
{
if (bitmap != null)
{
bitmap.Dispose(); //Without this, memory goes nuts
}
bitmap = new Bitmap(eventArgs.Frame);
}
catch { }
//Draw some stuff on the images
bitmap = AdjustBrightness(bitmap, brightnessMeter);
bitmap = ApplyContrast(contrastMeter, bitmap);
bitmap = Draw_Top_Line(bitmap);
bitmap = Draw_Bottom_Line(bitmap);
//Set the image into the picturebox
this.Invoke((MethodInvoker)delegate
{
videoPictureBox1.Image = bitmap;
frameRate++; //Keep track of the frame rate
});
GC.Collect(); //Without this, memory goes nuts
});
}
Shawn Hargreaves has an excellent, concise writeup of the "big red X of doom". I found it very helpful in the general case of dealing with WinForm components suddenly showing the red "X".
In summary:
This is caused by a control throwing an exception out of the OnPaint event.
Once it is thrown, that control will continue to show the red X and skip firing OnPaint.
To debug, set the debugger to catch Common Language Runtime Exceptions, and then do whatever you normally do to get the red X. The debugger will stop right where it is happening, allowing you to investigate and hopefully figure out a way to prevent it.
try using the clone in places where you use the bitmap.
Ex:
videoPictureBox1.Image = (Bitmap)bitmap.Clone();
Just to sum it up, this is a tested bare minimum that shows no red cross for me, even when resized, started, stoped or resolution changed.
public partial class PictureBoxVideo : Form
{
public PictureBoxVideo()
{
InitializeComponent();
var videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
var videoSource = new VideoCaptureDevice(videoDevices[0].MonikerString);
videoSource.NewFrame += Handle_Very_New_Frame;
videoSource.Start();
}
private void Handle_Very_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
this.Invoke((MethodInvoker)delegate {
pictureBox.Image = new Bitmap(eventArgs.Frame);
});
}
}
Please note, that we call videoSource.Start(); from the GUI-(creation)-thread, but the call back handler (Handle_Very_New_Frame) is called from the video (worker) thread.
I think that's why we need both, the Invoke and the new Bitmap, so the new bmp will also be generated from the gui-thread. But I'm just guessing here, as I couldn't come up with a proof.

.net barcode generation

I am developing a barcode generating web application using asp.net/c# ,I was wondering if it is better to use barcode library or a barcode font will be just enough.I have come across some samples but when using barcode font I found there is an asterisk(*) in front of the each code used for generating barcode.And I dint find any free barcode libraries. I want to generate code 39 or 93. Please help me decide
try jquery-barcode
Its a javascript library to generate bar codes. Check out this question for other alternatives.
Here is an extension method I am using that doesn't require you to install the font:
public static Image GetBarCode(this string data, int fontSizeEm)
{
data = "*" + data + "*";
Image img = null;
Graphics drawing = null;
try
{
using (var pfc = new PrivateFontCollection())
{
pfc.AddFontFile(#"{{PATH TO YOUR FONT FILE}}");
using (var myfont = new Font(pfc.Families[0], fontSizeEm))
{
img = new Bitmap(1, 1);
drawing = Graphics.FromImage(img);
var textSize = drawing.MeasureString(data, myfont);
img.Dispose();
drawing.Dispose();
img = new Bitmap((int) textSize.Width, (int) textSize.Height);
drawing = Graphics.FromImage(img);
drawing.DrawString(data, myfont, new SolidBrush(Color.Black), 0, 0);
}
drawing.Save();
}
return img;
}
catch
{
//Handle exception
return null;
}
finally
{
if(drawing!= null)
drawing.Dispose();
}
}
In my experience, libraries that generate barcodes via graphic primitives like rectangles are far superior to barcode fonts. Reasons:
Fonts are much larger, often orders of magnitude, and take much longer to transmit. This is especially problematic on serial connections.
The barcodes fonts produce are often less accurate as printers may try to anti-alias the bars.
Fonts are subject to things like styles, word-wrapping, font substitution, and other effects that make them difficult to control.
There are plenty of free barcode image libraries. If you didn't find any you did not look very well.
Barcode 3 of 9 requires guard bars at the start and end of the code so the scanner knows where the code starts and ends. When printing the legend for a code 3 of 9, these guard bars are traditionally shown as asterisks. These asterisks are only for humans reading the legend, they are not part of the code and in fact an asterisk is not a legal code 3 of 9 character. If you remove the guard bars the scanner would not be able to read the barcode.

Need some lite library/code that will create thumbnails and is optimal for use with ASP.NET MVC

Below is the action method that returns images from the database as they are, I need some lite library or write the code myself if short that will resize and compress these images according to my requirements "Make thumbnails" before they are passed to the HTTP response.
EDIT: Actually come to think of it, perhaps it would be best to save thumbnails in additional column, so now I need a way to compress and resize the images before they are saved to the database a long with saving a copy that is untouched. Saving images initially by passing them in HttpPostedFileBase and now need some tool that will resize and compress before saving to database.
public FileContentResult GetImage(int LineID)
{
var PMedia = repository.ProductMedias.FirstOrDefault(x => x.LineID == LineID);
if (PMedia != null)
{
return File(PMedia.ImageData, PMedia.ImageMimeType, PMedia.FileName);
}
else
{
return null;
}
}
Is your thumbnail size different everytime? Otherwise it is probably optimal to have another Column/Storage with Resized photos for your Thumbnails than processing them every time.
System.Drawing can be used to create thumbnails easily. However, its use is not supported for ASP.NET for a number of good reasons.
However however, if you took Erik Philips' suggestion and pre-generated all the thumbnails and stored them in the database alongside the originals, you would conceivably have a process of some sort (like a Windows service) that would periodically generate thumbs for rows that needed them. Because this process would generate the thumbs serially, you would not have the concerns about using System.Drawing as you would in an ASP.NET application (where you could easily have multiple threads gobbling up the relatively scarce system resources that System.Drawing wraps).
Edit: I just noticed the MVC tags. I don't know if System.Drawing is usable with MVC, or whether it's been superseded by something else. Generally, .NET has always had built-in useful graphics libraries that can do most simple things easily (I won't say it does simple things simply, as evidenced by the 30 overloads of the Graphics.DrawImage(...) method), so I expect you can still do this in MVC.
Don't reinvent a wheel ! There is a very nice, free (open-source in fact), pure .NET library, usable with API or handler :
http://imageresizing.net/
It supports very high quality resizing, converting to bunch of formats, auto-cropping, rotating, watermarking...
And if you think "nah, i can do it myself!", here is 20 reasons why you shouldnt :
http://nathanaeljones.com/163/20-image-resizing-pitfalls/
Here is routine that I use for making thumbnails :
public void MakeThumbnail(string imagePath)
{
// Image exists?
if (string.IsNullOrEmpty(imagePath)) throw new FileNotFoundException("Image does not exist at " + imagePath);
// Default values
string Filename = imagePath.ToLower().Replace(".jpg", "_thumb.jpg");
int Width = 100; // 180;
int Height = 75; // 135;
bool lSaved = false;
// Load image
Bitmap bitmap = new Bitmap(imagePath);
// If image is smaller than just save
try
{
if (bitmap.Width <= Width && bitmap.Height <= Height)
{
bitmap.Save(Filename, ImageFormat.Jpeg);
lSaved = true;
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
finally
{
bitmap.Dispose();
}
if (!lSaved)
{
Bitmap FinalBitmap = null;
// Making Thumb
try
{
bitmap = new Bitmap(imagePath);
int BitmapNewWidth;
decimal Ratio;
int BitmapNewHeight;
// Change size of image
Ratio = (decimal)Width / Height;
BitmapNewWidth = Width;
BitmapNewHeight = Height;
// Image processing
FinalBitmap = new Bitmap(BitmapNewWidth, BitmapNewHeight);
Graphics graphics = Graphics.FromImage(FinalBitmap);
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.FillRectangle(Brushes.White, 0, 0, BitmapNewWidth, BitmapNewHeight);
graphics.DrawImage(bitmap, 0, 0, BitmapNewWidth, BitmapNewHeight);
// Save modified image
FinalBitmap.Save(Filename, ImageFormat.Jpeg);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
finally
{
if (FinalBitmap != null) FinalBitmap.Dispose();
}
}
}

Categories

Resources