How can i show the current animated gif speed? - c#

I have this class that im getting the information from the animated gif:
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.IO;
public class AnimatedGif
{
private List<AnimatedGifFrame> mImages = new List<AnimatedGifFrame>();
public AnimatedGif(string path)
{
Image img = Image.FromFile(path);
int frames = img.GetFrameCount(FrameDimension.Time);
if (frames <= 1) throw new ArgumentException("Image not animated");
byte[] times = img.GetPropertyItem(0x5100).Value;
int frame = 0;
for (; ; )
{
int dur = BitConverter.ToInt32(times, 4 * frame);
mImages.Add(new AnimatedGifFrame(new Bitmap(img), dur));
if (++frame >= frames) break;
img.SelectActiveFrame(FrameDimension.Time, frame);
}
img.Dispose();
}
public List<AnimatedGifFrame> Images { get { return mImages; } }
}
public class AnimatedGifFrame
{
private int mDuration;
private Image mImage;
internal AnimatedGifFrame(Image img, int duration)
{
mImage = img; mDuration = duration;
}
public Image Image { get { return mImage; } }
public int Duration { get { return mDuration; } }
}
Then in Form1 in the constructor im looping over the List of images and get the duration of each of the images. So in the List in this case there are 4 images each one duration is 1.
So when im showing the animatd gif im trying to display the speed in a label.
But there are two problems:
The loop in the end show me that speed is now 2 not 4.
The label the result there is all the time 0 and 2/100 is not 0.
What i want to do is to show the actual speed.
Like in the program Easy gif animator 5:
If im standing on one image from the 4 i see that its speed is 0.01seconds wich is Delay 1 wich is 1/100th sec.
And if i mark all the images in the program i get speed 0.04 seconds.
Maybe i confusing between speed and duration.
I want to get the speed of the animated gif.
This is my code in Form1:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MyAnimatedGifEditor
{
public partial class Form1 : Form
{
int speed;
Image myImage;
AnimatedGif myGif;
public Form1()
{
InitializeComponent();
myImage = Image.FromFile(#"D:\fananimation.gif");
myGif = new AnimatedGif(#"D:\fananimation.gif");
for (int i = 0; i < myGif.Images.Count; i++)
{
speed = myGif.Images[i].Duration;
speed++;
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
pictureBox1.Image = myImage;
label2.Text = (speed / 100).ToString();
}
}
}
Image from the easy gif animator after selected all images:
In the end i want to show on two labels one the duration of the animated gif and one the speed.

There is a problem with the portion of your code where you are looping through the images of the animated gif. You probably want two separate variables here instead of just speed.
So something like
for (int i = 0; i < myGif.Images.Count; i++)
{
totalDuration += myGif.Images[i].Duration;
count++;
}
And to solve your integer math problem, divide by 100.0 instead of 100:
label2.Text = (totalDuration / 100.0).ToString();

Related

Calling xiCam.OpenDevice() for ximea camera raises exception "invalid handle"

I'm trying to control a Ximea camera (http://www.ximea.com) via a C# application.
I used an example that the company ships with the camera. Everytime I want to connect to the camera (using the OpenDevice function), I get an error that says - 'invalid handle'. What does this mean and what can I do to fix that?
Here is the code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Drawing;
using xiApi.NET;
namespace xiApi.NET_example
{
class Program
{
static void Main(string[] args){
{
xiCam myCam = new xiCam();
try
{
// Initialize first camera
myCam.OpenDevice(0);
// Set device exposure to 2 milliseconds
int exposure_us = 2000;
myCam.SetParam(PRM.EXPOSURE, exposure_us);
// Set device gain to 5 decibels
float gain_db = 5;
myCam.SetParam(PRM.GAIN, gain_db);
// Set image output format to monochrome 8 bit
myCam.SetParam(PRM.IMAGE_DATA_FORMAT, IMG_FORMAT.MONO8);
//Start acquisition
myCam.StartAcquisition();
// Capture images
Bitmap myImage;
int timeout = 1000;
for (int i = 0; i < 10; i++)
{
myCam.GetImage(out myImage, timeout );
string fName = string.Format("image{0}.bmp", i);
myImage.Save(fName);
}
// Stop acquisition
myCam.StopAcquisition();
}
catch (System.ApplicationException appExc)
{
// Show handled error
Console.WriteLine(appExc.Message);
System.Console.ReadLine();
myCam.CloseDevice();
}
finally
{
myCam.CloseDevice();
}

viola jones recognize faces with emgucv and C#

can viola jones recognize faces without any addition method like PCA or anything else ? how's the accurancity? and how to get rid the false negative in detecting? because there's so much false negative in viola jones detecting. if you know something please tell me.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Emgu.CV.Util;
using Emgu.CV.Features2D;
using Emgu.CV;
using Emgu.CV.GPU;
using Emgu.CV.VideoStab;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
namespace deteksi_wajah
{
public partial class Form1 : Form
{
Capture capture; // untuk koneksi ke webcam
HaarCascade haar;
public Form1()
{
InitializeComponent();
}
//method
//Proses image aquisision bertipe rgb
private void prosesFrame(object sender, EventArgs arg)
{
Image < Bgr, byte > image = capture.QueryFrame(); //hasil koneksi gambar didapat bertipe rbg
imageBox1.Image = image; // citra yg didapat berada dalam box
if( image != null)
{
Image < Gray, byte > gray = image.Convert<Gray,byte>();
var faces = gray.DetectHaarCascade(haar, 1.1 , 1,
Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING, new Size(20,20))[0];
foreach (var face in faces)
{
Image<Gray,byte>hasil = image.Copy(face.rect).Convert<Gray,byte>().Resize(100, 100, INTER.CV_INTER_CUBIC);
image.Draw(face.rect, new Bgr(Color.Red),3);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
if (capture == null)
{
try
{
capture = new Capture();
}
catch
{
}
}
//jika camera tidak sama dengan null
if (capture != null)
{
if (btn_start.Text == "Pause")
{
btn_start.Text = "Resume";
Application.Idle -= prosesFrame; // mengaktifkan kamera
}
else
{
btn_start.Text = "Pause";
Application.Idle += prosesFrame;
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
haar = new HaarCascade("haarcascade_frontalface_default.xml");
}
}
}
I think the problem with your code is the parameters in detection are too small.
gray.DetectHaarCascade(haar, 1.1 , 1,
Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING, new Size(20,20))
Try increase the minNeighbor and minSize value. minNeighbor = 1 do no grouping and cause a lot of false positive. For me, with my current camera at 1280*720 resolution, minNeighbor = 10 and minSize = 100,100 did a very good job.

Continuously desktop region capture failed after some time - Unhandled exception in System.Drawing.dll (parameter is not valid)

I am making a an app where I have to capture selected desktop region continuously(using "Timer(CaptureTimer)" with interval 100) , resize it , make it to dither image & show it to "PictureBox(PreviewPictureBox)".
My app has two "Form"s.
One is "MainForm" contains "PreviewPictureBox" & "Button(StartButton)" & other is "CaptureForm" contains "CapturePictureBox".
"CaptureForm(size is 646x326)" is transparent & FromBorderStyle = none.
"CapturePictureBox" is "dock in parent container" & has a side bordered & middle transparent png picture in it.
"CaptureForm" can be move by click & dragging the "CapturePictureBox".
This is "MainForm"
Here is "MainForm" Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace _128x64_GLCD_Monitor
{
public partial class MainForm : Form
{
CaptureForm CapF = new CaptureForm();
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
}
public Bitmap ScreenCaptureBitmap(int DesktopX, int DesktopY, int CaptureWidth, int CaptureHeight)
{
Bitmap ScreenCaptureBmp = new Bitmap(CaptureWidth, CaptureHeight);
Graphics graphics = Graphics.FromImage(ScreenCaptureBmp as Image);
graphics.CopyFromScreen(DesktopX, DesktopY, 0, 0, ScreenCaptureBmp.Size);
return ScreenCaptureBmp;
}
public Bitmap ResizeBitmap(Bitmap ResizeBmp, int RBmpWidth, int RBmpHeight)
{
Bitmap RBmp = new Bitmap(RBmpWidth, RBmpHeight);
using (Graphics RBmpG = Graphics.FromImage((Image)RBmp))
RBmpG.DrawImage(ResizeBmp, 0, 0, RBmpWidth, RBmpHeight);
return RBmp;
}
public Bitmap DitherBitmap(Bitmap DitherBmp) // Not writing full method here
private void StartButton_Click(object sender, EventArgs e)
{
CapF.Show();
CaptureTimer.Start();
}
private void CaptureTimer_Tick(object sender, EventArgs e)
{
int windowLeft = CapF.Left + 3;
int windowTop = CapF.Top + 3;
int windowWidth = CapF.Width - 6;
int windowHeight = CapF.Height - 6;
Bitmap Pic = ScreenCaptureBitmap(windowLeft, windowTop, windowWidth, windowHeight);
Bitmap Pic1 = ResizeBitmap(Pic, 128, 64);
Bitmap Pic2 = DitherBitmap(Pic1);
PreviewPictureBox.Image = Pic2;
}
}
}
This is "CaptureForm"
Here is "CaptureForm" Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace _128x64_GLCD_Monitor
{
public partial class CaptureForm : Form
{
Boolean TogMove;
int MValX, MValY;
public CaptureForm()
{
InitializeComponent();
}
private void CaptureForm_Load(object sender, EventArgs e)
{
TransparencyKey = BackColor;
}
private void CapturePictureBox_MouseDown(object sender, MouseEventArgs e)
{
TogMove = true;
MValX = e.X;
MValY = e.Y;
}
private void CapturePictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (TogMove == true)
{
this.SetDesktopLocation(MousePosition.X - MValX, MousePosition.Y - MValY);
}
}
private void CapturePictureBox_MouseUp(object sender, MouseEventArgs e)
{
TogMove = false;
}
}
}
When I start debugging, after some time(after completing some loop) it getting this message
Visual Studio 2010 pointed this line(at a 1 time debugging 1 line)
Some time this line
Bitmap ScreenCaptureBmp = new Bitmap(CaptureWidth, CaptureHeight);
Or some time this line
graphics.CopyFromScreen(DesktopX, DesktopY, 0, 0, ScreenCaptureBmp.Size);
From this method
public Bitmap ScreenCaptureBitmap(int DesktopX, int DesktopY, int CaptureWidth, int CaptureHeight)
What I have to do to prevent this error?
Make sure the following 4 variables are within the size of the Form. When you click the numbers can be negative or greater than the size (width , height) of the form. :
int windowLeft = CapF.Left + 3;
int windowTop = CapF.Top + 3;
int windowWidth = CapF.Width - 6;
int windowHeight = CapF.Height - 6;
It looks like the values for windowLeft, WindowTop, windowWidth or windowHeight in your timer methode, went negative.
If you only want to prevent this error, you can simply set the values in an if-clause before you call the method ScreenCaptureBitmap(...) or you prevent the dragging to negative values in the LocationChanges-Event.

Making an updating winform multi threaded

I have been breaking my head over this for a long time now and I can't seem to find how to solve this. Simply put I need to present Parallel programming to my class and i am making a demo that clearly shows the diffrence between single threaded and multi threaded.
First the program takes a screenshot and loads that in this class into a bitmap.
Then it loads the winform with a picturebox called screenshot. Next it does Form1_Load and loads the screenshot into the picturebox.
Then Form1_Shown Runs the for loop which just scrambles the pixels around based on a randomizer and updates the image from the left to the right.
example: http://gyazo.com/ab04583bb33de59d08407886da1c4870
This all works.
I now want to make it so that the screenshot is being updated from the left to the middle by the first thread, and from the middle to the right with the second thread.
But when i put it in 2 separate threads it says "An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll"
The error implies I am making illegal cross thread calls. Particulary on screenshot and probably also on mybitmap.
Visual studio helps me by linking me to "How to: Make Thread-Safe Calls to Windows Forms Controls"
But i am not getting any wiser out of this information which is probably because i am not that fluent with the C# terminology yet.
How should i approach/fix this ?
This is the class where everything happens (except taking the screenshot):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ScreenOutput
{
public partial class Form1 : Form
{
PictureBox screenshot;
Bitmap myBitmap = new Bitmap(#".\screenshot.jpg");
public Form1()
{
InitializeComponent();
}
private int Xcount;
private int Ycount;
private int maxXValue = Screen.PrimaryScreen.Bounds.Width - 1;
private int maxXValueT1 = 960;
private int maxXValueT2 = 1919;
private int maxYValue = Screen.PrimaryScreen.Bounds.Height - 1;
private int maxYValueT1 = 539;
private int maxYValueT2 = 1079;
private void Form1_Load(object sender, EventArgs e)
{
screenshot.Image = myBitmap;
}
private void Form1_Shown(object sender, EventArgs e)
{
Thread startThread1 = new Thread(new ThreadStart(thread1));
Thread startThread2 = new Thread(new ThreadStart(thread2));
startThread1.Start();
startThread2.Start();
Thread.Sleep(10000); //waiting for completion
startThread1.Abort();
startThread2.Abort();
//this is how it would work without multithreading
/*Random random = new Random();
for (Xcount = 0; Xcount < maxXValue; Xcount++)
{
screenshot.Refresh();
for (Ycount = 0; Ycount < maxYValue; Ycount++)
{
int calculatedX = Xcount + random.Next(0, maxXValue);
if (calculatedX > maxXValue) calculatedX = maxXValue;
myBitmap.SetPixel(Xcount, Ycount, myBitmap.GetPixel(calculatedX, Ycount));
}
}
Thread.Sleep(2000);*/
Application.Exit();
}
public void thread1()
{
Random random = new Random();
for (Xcount = 0; Xcount < maxXValueT1; Xcount++)
{
screenshot.Refresh();
for (Ycount = 0; Ycount < maxYValueT1; Ycount++)
{
int calculatedX = Xcount + random.Next(0, maxXValueT1);
if (calculatedX > maxXValue) calculatedX = maxXValueT1;
myBitmap.SetPixel(Xcount, Ycount, myBitmap.GetPixel(calculatedX, Ycount));
}
}
}
public void thread2()
{
Random random = new Random();
for (Xcount = 0; Xcount < maxXValueT2; Xcount++)
{
screenshot.Refresh();
for (Ycount = 0; Ycount < maxYValueT2; Ycount++)
{
int calculatedX = Xcount + random.Next(0, maxXValueT2);
if (calculatedX > maxXValueT2) calculatedX = maxXValueT2;
myBitmap.SetPixel(Xcount, Ycount, myBitmap.GetPixel(calculatedX, Ycount));
}
}
}
}
}
You will need to Invoke the GUI thread.
I prefer the following solution.
Using a Form member ('screenshot' in this case) check to see if InvokeRequired = true. If so then Invoke a delegate using that members BeginInvoke() function as the following example demonstrates:
private void ScreenshotRefresh()
{
if(screenshot.InvokeRequired)
{
screenshot.BeginInvoke(new MethodInvoker(this.ScreenshotRefresh));
}
else
{
screenshot.Refresh();
}
}

Why when creating screenshot captured files on hard disk and make of them avi it's very slow?

What i mean is i have this code i'm creating many gif files on the hard disk using a timer to capture the desktop window. Every 1 second i'm taking a screenshot.
For example after 60 seconds i have on the hard disk only 60 gif files.
Then i'm using my own animated gif class to create animated gif.
When i'm playing the animated gif it seems that many frames are missing.
Now i'm taking screenshots of the dekstop window every second a screenshot.
But i think i should take every second like 25 screenshots or 60 ?
How can i do it ?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing.Imaging;
using System.IO;
using unfreez_wrapper;
namespace CapturedDesktop
{
public partial class Form1 : Form
{
int screens;
string gifsdirectory;
UnFreezWrapper unfreez;
public Form1()
{
InitializeComponent();
unfreez = new UnFreezWrapper();
screens = 0;
gifsdirectory = #"C:\Temp\CapturedDesktop\";
}
private void CaptureScreenshot()
{
screens++;
screenshots(gifsdirectory + screens.ToString("D6") + ".gif");
}
public static void screenshots(string filename)
{
//Create a new bitmap.
using (var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width - 100,
Screen.PrimaryScreen.Bounds.Height - 100,
PixelFormat.Format32bppArgb))
{
// Create a graphics object from the bitmap.
using (var gfxScreenshot = Graphics.FromImage(bmpScreenshot))
{
// Take the screenshot from the upper left corner to the right bottom corner.
gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0,
0,
Screen.PrimaryScreen.Bounds.Size,
CopyPixelOperation.SourceCopy);
}
// Save the screenshot to the specified path that the user has chosen.
bmpScreenshot.Save(filename, ImageFormat.Gif);
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
CaptureScreenshot();
}
private void AnimatedGifButton_Click(object sender, EventArgs e)
{
List<string> myGifList = new List<string>();
FileInfo[] fi;
DirectoryInfo dir1 = new DirectoryInfo(gifsdirectory);
fi = dir1.GetFiles("*.gif");
for (int i = 0; i < fi.Length; i++)
{
myGifList.Add(fi[i].FullName);
}
unfreez.MakeGIF(myGifList, gifsdirectory + "agif", 100, true);
}
}
}
The problem is not the animated gif speed when i create it but it's not smooth it's like missing frames.

Categories