I want to merge two .png images. but when I ga to save them there occurred an error called a generic error occurred in gdi+. I want to continue my project as soon as possible. please help me. Thanks
private void MergeImages(string ImageBack,string ImageFore)
{
try
{
System.Drawing.Graphics myGraphic = null;
Image imgB;// =new Image.FromFile(ImageBack);
imgB = Image.FromFile(ImageBack);
//FileInfo fileInfoBack = new FileInfo(ImageBack);
Image imgF;// =new Image.FromFile(ImageBack);
imgF = Image.FromFile(ImageFore);
//Bitmap tempBitmap = new Bitmap(imgB.Width, imgB.Height,imgB.PixelFormat );
// tempBitmap.Save("a"+fileInfoBack.Extension);
Image m;
m = Image.FromFile(ImageBack);
// m = Image.FromFile("a" + fileInfoBack.Extension);
myGraphic = System.Drawing.Graphics.FromImage(m);
myGraphic.DrawImageUnscaled(imgB,0,0);
myGraphic.DrawImageUnscaled(imgF,posX,posY);
myGraphic.Save();
m.Save(ImageBack.Replace(".jpg",".jpeg"),System.Drawing.Imaging.ImageFormat.Jpeg);
//m.Save(ImageBack, System.Drawing.Imaging.ImageFormat.Png);
// m.Save("d.png", System.Drawing.Imaging.ImageFormat.Png);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnFileProtector_Click(object sender, System.EventArgs e)
{
if (openFileDialog1.ShowDialog()==DialogResult.OK)
{
txtFileProtector.Text=openFileDialog1.FileName;
}
}
private void btnFilesToProtect_Click(object sender, System.EventArgs e)
{
listFilesToProtect.Items.Clear();
if (openFileDialog2.ShowDialog()==DialogResult.OK)
{
if (openFileDialog2.FileNames.Length>0)
{
for(int i=0;i<openFileDialog2.FileNames.Length;i++)
{
listFilesToProtect.Items.Add(openFileDialog2.FileNames[i]);
}
}
}
}
private void btnLoad2_Click(object sender, System.EventArgs e)
{
posX = int.Parse(textBox1.Text);
posY = int.Parse(textBox2.Text);
// heightBackImage = int.Parse(textBox3.Text);
// widthBackImage = int.Parse(textBox4.Text);
if (listFilesToProtect.Items.Count>0)
{
foreach(object it in listFilesToProtect.Items)
{
MergeImages(it.ToString(), txtFileProtector.Text);
}
}
}
You didn't show us at which line this exception is thrown, So I am going to guess here. This error usually occurs when the path of the image that you are trying to load/save is not correct, so check the path for both ImageBack and ImageFore.
Also make sure that the file you are trying to load/save to is not open by another process including your application.
It is worth to mentioned here that you should dispose the images/graphics when you finish from using them, for instance by use using. like
using(Image imgB = Image.FromFile(ImageBack))
{
//the code that is using the imgB here
}
Related
I keep getting a "Parameter is not valid" error or a memory leak (and the picture doesn't update) when I run my code. I am trying to get frames from a local IP camera using AForge.Net. The exact error code that I get is:
"An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll
Parameter is not valid."
In my code, feed is the name of the winforms picture box.
private void Form1_Load(object sender, EventArgs e) {
Console.WriteLine(camaddress);
stream.Source = camaddress;
stream.Login = camUser;
stream.Password = camPass;
stream.Start();
//PictureBox.CheckForIllegalCrossThreadCalls = false;
CaptureCamera();
isCameraRunning = true;
}
private void CaptureCamera() {
try {
camera = new Thread(new ThreadStart(CaptureCameraCallback));
camera.Start();
} catch (Exception e) {
Debug.Write("Exception encountered trying to capture camera:\n" + e.ToString() + "\n");
}
}
private void CaptureCameraCallback() {
log.Information("Camera Opened", testID);
guiLogWrite("Camera Opened");
while (stream.IsRunning) {
stream.NewFrame += new NewFrameEventHandler(VideoStream_NewFrame);
}
}
private void VideoStream_NewFrame(object sender, NewFrameEventArgs eventArgs) {
try {
//Image FrameData = new Bitmap(eventArgs.Frame);
if (feed.Image != null) feed.Image.Dispose();
Bitmap FrameData = AForge.Imaging.Image.Clone(eventArgs.Frame);
SetPicture(FrameData);
FrameData.Dispose();
} catch { }
}
private void SetPicture(Image img) {
if (this.InvokeRequired) {
this.Invoke(new MethodInvoker(delegate { SetPicture(img); }));
} else {
this.feed.Image = img;
}
This is my first time posting on Stack Overflow so please let me know if I have forgotten something. I've spent hours looking at other stackoverflow threads and Google trying to find a solution.
With this code i can play video files from my hard disk and show the video in pictureBox1. But i wonder how can i save all the frames of the video to images files on the hard disk ? While playing the video or without playing i need somehow to extract the frames and save them.
This is my used code so far:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
IGraphBuilder m_graphBuilder = null;
IMediaControl m_mediaCtrl = null;
IMediaEventEx m_mediaEvt = null;
IMediaPosition m_mediaPos = null;
IMediaSeeking m_mediaSeeking = null;
public Form1()
{
InitializeComponent();
}
void InitInterfaces()
{
try
{
m_graphBuilder = (IGraphBuilder)new FilterGraph();
m_mediaCtrl = (IMediaControl)m_graphBuilder;
m_mediaEvt = (IMediaEventEx)m_graphBuilder;
m_mediaPos = (IMediaPosition)m_graphBuilder;
m_mediaSeeking = (IMediaSeeking)m_graphBuilder;
}
catch (Exception)
{
MessageBox.Show("Couldn't start directshow graph");
}
}
void CloseInterfaces()
{
if (m_mediaCtrl != null)
{
m_mediaCtrl.StopWhenReady();
}
m_mediaCtrl = null;
m_mediaEvt = null;
m_mediaPos = null;
m_mediaSeeking = null;
if (m_graphBuilder != null)
Marshal.ReleaseComObject(this.m_graphBuilder);
m_graphBuilder = null;
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void SetuupVideoRenderer()
{
IBaseFilter vmrFilter = null;
vmrFilter = (IBaseFilter)new VideoMixingRenderer();
m_graphBuilder.AddFilter(vmrFilter, "Video Renderer");
IVMRFilterConfig FilterConfig = (IVMRFilterConfig)vmrFilter;
FilterConfig.SetRenderingMode(VMRMode.Windowless);
IVMRWindowlessControl windowlessCtrl = (IVMRWindowlessControl)vmrFilter;
windowlessCtrl.SetVideoClippingWindow(this.pictureBox1.Handle);
windowlessCtrl.SetVideoPosition(null, DsRect.FromRectangle(pictureBox1.ClientRectangle));
windowlessCtrl.SetAspectRatioMode(VMRAspectRatioMode.LetterBox);
}
private void buttonLoad_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "All Files (*.*)|*.*|mp4 (*.mp4)|*.mp4|mov (*.mov)|*.mov||";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
CloseInterfaces();
InitInterfaces();
SetuupVideoRenderer();
m_graphBuilder.RenderFile(openFileDialog1.FileName, null);
textBoxDur.Text = ( getDuration() * 0.0000001).ToString();
m_mediaCtrl.Run();
timer1.Enabled = true;
}
}
private void GetPosition(out long CurrentPos,out long StopPos)
{
m_mediaSeeking.GetPositions(out CurrentPos, out StopPos);
}
private long getDuration()
{
long duration;
m_mediaSeeking.GetDuration(out duration);
return duration;
}
private void SetPos(double fPos)
{
DsLong startPosition = (DsLong)(10000000 * fPos);
m_mediaSeeking.SetPositions(startPosition, AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning);
}
private void buttonPause_Click(object sender, EventArgs e)
{
m_mediaCtrl.Pause();
}
private void buttonPlay_Click(object sender, EventArgs e)
{
m_mediaCtrl.Run();
}
private void OnVideoCompleted()
{
MessageBox.Show("Video Playback Completed");
}
private void timer1_Tick(object sender, EventArgs e)
{
long iCurPos, iStopPos;
GetPosition(out iCurPos, out iStopPos);
if (iCurPos >= iStopPos)
{
timer1.Enabled = false;
OnVideoCompleted();
return;
}
textBoxCurPos.Text = (iCurPos * 0.0000001 ).ToString();
}
private void buttonGo_Click(object sender, EventArgs e)
{
SetPos(Convert.ToDouble(textBoxNewPos.Text));
timer1.Enabled = true;
}
}
}
I think this is excatly what you are looking for:
extract frames of a video
Have a look as well at this SO question and the links provided on this webpage.
The easiest way to do it is indeed using an FFMPEG, since its alredy includes some of the most common codecs (if you dont mind extra 30+Mb added to your app). As for wrappers, i used AForge wrapper in the past and really liked it, because of how simple it is to work with. Here is an example from its docs:
// create instance of video reader
VideoFileReader reader = new VideoFileReader();
// open video file
reader.Open( "test.avi");
// read 100 video frames out of it
for ( int i = 0; i < 100; i++)
{
Bitmap videoFrame = reader.ReadVideoFrame();
videoFrame.Save(i + ".bmp")
// dispose the frame when it is no longer required
videoFrame.Dispose( );
}
reader.Close();
I wrote a program, code seems working but it is not working. It gives IO exception was unhandled error. Some guys say me , you should delete something because program try to use same file at the same time. Please help me!!
namespace App1508
{
public partial class Form2 : Form
{
string goodDir = "C:\\GOOD\\";
string badDir = "C:\\BAD\\";
string fromDir = "C:\\DENEME\\";
List<Image> images = null;
int index = -1;
FileInfo[] finfos = null;
public Form2()
{
InitializeComponent();
DirectoryInfo di = new DirectoryInfo(#"C:\DENEME");
finfos = di.GetFiles("*.jpg",SearchOption.TopDirectoryOnly);
images = new List<Image>();
foreach (FileInfo fi in finfos)
{
images.Add(Image.FromFile(fi.FullName));
}
}
private void button1_Click(object sender, EventArgs e)
{
finfos[index].MoveTo(Path.Combine("C:\\GOOD", finfos[index].Name));
}
private void pictureBox1_Click(object sender, EventArgs e)
{
index++;
if (index < 0 || index >= images.Count)
index = 0;
pictureBox1.Image = images[index];
}
private void button2_Click(object sender, EventArgs e)
{
finfos[index].MoveTo(Path.Combine("C:\\BAD", finfos[index].Name));
}
}
}
This is the problem:
foreach (FileInfo fi in finfos)
{
images.Add(Image.FromFile(fi.FullName));
}
Image.FromFile will open a file handle, and won't close it until you dispose of the image. You're trying to move the file without disposing of the image which has that file open first.
I suspect if you dispose of the relevant image in your button1_Click and button2_Click methods (being aware that if it's showing in the PictureBox you'll need to remove it from there first) you'll find it works.
Ref:
http://support.microsoft.com/?id=814675
When I open a form which is created at runtime for the second time , I keep getting an error saying "Cannot access a disposed object." "Object name 'Form'" Here is the code of the function. It is called by a buttonclick event. I have looked all over the Net and found people with similar problems, however I have tried those fixes and none of them work. Not sure how to fix this problem. VS highlights the line frmFavorites.Show();
Thank you in advance.
public void frmMyBrowser_ShowFavorites(object sender, EventArgs e)
{
frmFavorites.ShowIcon = false;
frmFavorites.ShowInTaskbar = false;
frmFavorites.Text = "Bookmarks";
frmFavorites.Width = 500;
frmFavorites.Height = 320;
frmFavorites.Controls.Add(lstFavorites);
frmFavorites.Controls.Add(btnRemoveFavorite);
frmFavorites.Controls.Add(btnAddFavorite);
frmFavorites.Controls.Add(txtCurrentUrl);
lstFavorites.Width = 484;
lstFavorites.Height = 245;
btnRemoveFavorite.Location = new Point(397, 255);
btnAddFavorite.Location = new Point(8, 255);
txtCurrentUrl.Location = new Point(110, 255);
txtCurrentUrl.Size = new Size(265, 20);
btnAddFavorite.Text = "Add";
btnRemoveFavorite.Text = "Remove";
txtCurrentUrl.Text = wbBrowser.Url.ToString();
btnAddFavorite.Click += new EventHandler(btnAddFavorite_Click);
btnRemoveFavorite.Click += new EventHandler(btnRemoveFavorite_Click);
frmFavorites.Load += new EventHandler(frmFavorites_Load);
frmFavorites.Show();
frmFavorites.FormClosed += new FormClosedEventHandler(frmFavorites_FormClosed);
StreamReader reader = new System.IO.StreamReader(#Application.StartupPath + "\\favorites.txt");
{
while (!reader.EndOfStream)
{
for (int i = 0; i < 4; i++)
{
string strListItem = reader.ReadLine();
if (!String.IsNullOrEmpty(strListItem))
{
lstFavorites.Items.Add(strListItem);
}
}
}
reader.Close();
}
}
public void btnAddFavorite_Click(object sender, EventArgs e)
{
lstFavorites.Items.Add(wbBrowser.Url.ToString());
}
public void btnRemoveFavorite_Click(object sender, EventArgs e)
{
try
{
lstFavorites.Items.RemoveAt(lstFavorites.SelectedIndices[0]);
}
catch
{
MessageBox.Show("You need to select an item", "Error");
}
}
public void frmFavorites_Load(object sender, EventArgs e)
{
}
public void frmFavorites_FormClosed(object sender, FormClosedEventArgs e)
{
StreamWriter writer = new System.IO.StreamWriter(#Application.StartupPath + "\\favorites.txt");
{
for (int i = 0; i < lstFavorites.Items.Count; i++)
{
writer.WriteLine(lstFavorites.Items[i].ToString());
}
writer.Close();
}
frmFavorites.Close();
}
You cannot reopen a form that has been closed. When a form is closed (1) it is disposed and (2) the underlying operating system Window handle is freed.
I guess you might be able to take the contents of the Form's constructor and put it into a method that you could call to reopen the form, but I really wouldn't recommend doing that even if it does work.
Instead, just create a new instance of the form.
Try this
public void frmMyBrowser_ShowFavorites(object sender, EventArgs e)
{
frmFavorites = new Form();
....
....
}
I am loading the images using the BackgroundThread. I am receving "nullreferenceexception unhandled by user code" after loading all the images into the Listview. What could be the issue? Please let me know.
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
int progress = 0;
string pname;
Image myImage;
max_length = files.Length;
for (int k = 0; k < files.Length; k++)
{
ProgressInfo info = new ProgressInfo();
pname = System.IO.Path.GetFullPath(files[k]);
myImage = Image.FromFile(pname);
info.Image = myImage;
info.ImageIndex = k;
backgroundWorker1.ReportProgress(progress, info);
myImage = null;
}
}
catch (Exception ex)
{
throw ex.InnerException;
}
}
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
try
{
//Get image.
ProgressInfo img = e.UserState as ProgressInfo;
//Set image to ListView here.
ImgListView.Images.Add(getThumbnaiImage(ImgListView.ImageSize.Width, img.Image));
fname = System.IO.Path.GetFileName(files[img.ImageIndex]);
ListViewItem lvwItem = new ListViewItem(fname, img.ImageIndex);
lvwItem.Tag = files[img.ImageIndex];
lstThumbNailView.Items.AddRange(new ListViewItem[] { lvwItem });
percent = (int)((float)100 * (float)i / (float)files.Length);
this.progressBar1.Value = (int)percent;
this.label1.Text = "Loading images...";
}
catch (Exception ex)
{
throw ex.InnerException;
}
}
Judging from your comments, you're seeing the error because not all exceptions have an InnerException. If InnerException is null, you will see this problem.
There are several issues at work here though. First, here is the proper try/catch method:
try
{
// Code here
}
catch (Exception ex)
{
// Handle your exception
throw; // Rethrow the same exception, preserving the stack trace (optional)
}
Second, you are likely abusing the purpose of ReportProgress. You should attempt to do all your logic in your backgroundWorker_DoWork, and send the percentage (between 0 and 100) to ReportProgress to update any progress bars.
You may have used the ReportProgress in the way you did to fix a multi-threaded issue. To add items to a ListBox across threads, wrap your code in an anonymous method using the BeginInvoke function
Example:
// Note: I haven't error checked this, and this is only a rough idea of what
// you're trying to do. I'm not even sure of the overall goal here.
this.lstThumbnailView.Invoke((Action)delegate
{
ListViewItem lvwItem = new ListViewItem(name, img.ImageIndex);
ivwItem.Tag = files[img.ImageIndex];
lstThumbNailView.Items.Add(lvwItem);
});
Thanks for the quick response. Here are the changes I made. It seems to be working fine.
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
try
{
ProgressInfo img = e.UserState as ProgressInfo;
LoadImages(img);
this.progressBar1.Value = img.Percent;
this.label1.Text = "Loading images...";
}
catch (Exception ex)
{
throw ex;
}
}
private void LoadImages(ProgressInfo img)
{
ImgListView.Images.Add(getThumbnaiImage(ImgListView.ImageSize.Width, img.Image));
this.lstThumbNailView.Invoke((Action)delegate
{
fname = System.IO.Path.GetFileName(files[img.ImageIndex]);
ListViewItem lvwItem = new ListViewItem(fname, img.ImageIndex);
lvwItem.Tag = files[img.ImageIndex];
lstThumbNailView.Items.Add(lvwItem);
});
}