How can i release Image memory? - c#

I'm currently working on the code to take pictures with a Canon camera and float them on the image.
The problem right now is that the picture is displayed normally in the image, but the memory is allocated, but the memory is not released and keeps stacking.
The size of the picture is 6000 X 4000 and the picture is saved as JPG. Also, the capacity of the picture is 6MB.
How can I turn off the memory?
Below is a picture of the memory graph.
case 1:
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate {
var firstphoto = new BitmapImage();
var stream1 = File.OpenRead(MainWindow.PhotoPath + #"\IMG_" + photonumber + #".JPG");
firstphoto.BeginInit();
firstphoto.CacheOption = BitmapCacheOption.OnLoad;
firstphoto.StreamSource = stream1;
firstphoto.EndInit();
firstphoto.Freeze();
FirstPic.Source = firstphoto;
stream1.Close();
stream1.Dispose();
}));
break;
case 2:
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate {
var secondphoto = new BitmapImage();
var stream2 = File.OpenRead(MainWindow.PhotoPath + #"\IMG_" + photonumber + #".JPG");
secondphoto.BeginInit();
secondphoto.CacheOption = BitmapCacheOption.OnLoad;
secondphoto.StreamSource = stream2;
secondphoto.EndInit();
secondphoto.Freeze();
SecondPic.Source = secondphoto;
stream2.Close();
stream2.Dispose();
}));
break;
case 3:
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate {
var thirdphoto = new BitmapImage();
var stream3 = File.OpenRead(MainWindow.PhotoPath + #"\IMG_" + photonumber + #".JPG");
thirdphoto.BeginInit();
thirdphoto.CacheOption = BitmapCacheOption.OnLoad;
thirdphoto.StreamSource = stream3;
thirdphoto.EndInit();
thirdphoto.Freeze();
ThirdPic.Source = thirdphoto;
stream3.Close();
stream3.Dispose();
}));
break;
case 0:
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate {
var fourthphoto = new BitmapImage();
var stream4 = File.OpenRead(MainWindow.PhotoPath + #"\IMG_" + photonumber + #".JPG");
fourthphoto.BeginInit();
fourthphoto.CacheOption = BitmapCacheOption.OnLoad;
fourthphoto.StreamSource = stream4;
fourthphoto.EndInit();
fourthphoto.Freeze();
FourthPic.Source = fourthphoto;
stream4.Close();
stream4.Dispose();
}));

Related

BitmapFrame.Create cannot access this object

I'm trying to export several BitmapSource images from to png files. Here's my code:
Thread Call:
var exportImagesThread = new Thread(ExportRangeOfImages);
exportImagesThread.Start();
Function:
private void ExportRangeOfImages()
{
for (var currentFrame = exportFromFrame; currentFrame <= exportToFrame; currentFrame++)
{
var currentImage = Application.Current.Dispatcher.Invoke(() => (currentStream.Children[0] as Image).Source);
var pngBitmapEncoder = new PngBitmapEncoder();
var bitmapFrame = BitmapFrame.Create((BitmapSource) currentImage);
Application.Current.Dispatcher.Invoke(() => pngBitmapEncoder.Frames.Add(bitmapFrame));
var a = new FileStream(updatedDir + sequenceFile + "_" + frameNumber + ".png", FileMode.Create);
pngBitmapEncoder.Save(a);
}
}
When doing that I'm receiving Additional information: The calling thread cannot access this object because a different thread owns it. On line: var bitmapFrame = BitmapFrame.Create((BitmapSource) currentImage);
What am I missing?

An unhandled exception of type 'System.OutOfMemoryException' occurred in System.Drawing.dll

I'm trying to loop through all the images I load, I'm able to process up to 40 images, then the I get the Out of memory error although I'm disposing the variable tempImage. The code breaks at the "Bitmap tempImage = new Bitmap(fileName);" line, plz help!
Is there a way to handle large number of input files? Like batch process and splitting the process into chunks? Because the operation would last more than a minute to finish, the program would crash by then.
foreach (string fileName in openFileDialog.FileNames)
{
circleDetection examDetect = new circleDetection();
Bitmap tempImage = new Bitmap(fileName);
directory.Text = fileName;
PictureBox picBox = new PictureBox();
picBox.Width = 200;
picBox.Height = 200;
picBox.Location = new System.Drawing.Point(picBoard.Controls.Count * (picBox.Width + 5) + 5, 5);
picBox.SizeMode = PictureBoxSizeMode.Zoom;
picBox.BorderStyle = BorderStyle.FixedSingle;
examDetect.ProcessImage(tempImage);
picBox.Image = examDetect.getImage();
Console.WriteLine(i++);
student.Add(compare(examDetect));
picBoard.Controls.Add(picBox);
tempImage.Dispose();
}
I prefer to use using() instead of .Dispose(). It's also disposing an object after it's cycle ended. So maybe you should try smth like next?
foreach (string fileName in openFileDialog.FileNames)
{
circleDetection examDetect = new circleDetection();
using (Bitmap tempImage = new Bitmap(fileName))
{
Exam.Add(tempImage);
directory.Text = fileName;
PictureBox picBox = new PictureBox();
picBox.Width = 200;
picBox.Height = 200;
picBox.Location = new System.Drawing.Point(picBoard.Controls.Count * (picBox.Width + 5) + 5, 5);
picBox.SizeMode = PictureBoxSizeMode.Zoom;
picBox.BorderStyle = BorderStyle.FixedSingle;
examDetect.ProcessImage(tempImage);
picBox.Image = examDetect.getImage();
Console.WriteLine(i++);
student.Add(compare(examDetect));
picBoard.Controls.Add(picBox);
}
}
See MSDN for more information about using statement.
UPDATE:
But, why don't you use stream for loading your files? It's recommended to use stream for such cases.

Cannot delete file in C#.net windows application

I am first creating Bitmap image file and saving it to some temp location. Later using that file to read in BitmapImage object to compare it with other file. Once comparison is done, I want to delete file but then it throws exception that file is being used by another process. How can I delete this file?
Here is my code:
private void btnLogin_Click(object sender, EventArgs e)
{
string strPath = AppDomain.CurrentDomain.BaseDirectory;
GC.Collect();
if (txtLoginImage.Text != "")
{
string strFileName = txtLoginImage.Text.Substring(txtLoginImage.Text.LastIndexOf('\\') + 1);
Bitmap MainImg = new System.Drawing.Bitmap(txtLoginImage.Text);
Bitmap NewImage = ConvertToGrayScale(MainImg);
NewImage.Save(AppDomain.CurrentDomain.BaseDirectory + "\\Images\\Temp\\" + strFileName, System.Drawing.Imaging.ImageFormat.Bmp);
NewImage.Dispose();
Uri SourceUri = new Uri(AppDomain.CurrentDomain.BaseDirectory + "\\Images\\Temp\\" + strFileName);
BitmapImage source = new BitmapImage();
source.UriSource = SourceUri;
IrisSystem.Class.BLL.User_BLL ubll = new IrisSystem.Class.BLL.User_BLL();
DataSet dsUserData= ubll.getlist();
bool isMatchFound = false;
if (dsUserData != null && dsUserData.Tables.Count > 0)
{
foreach (DataRow item in dsUserData.Tables[0].Rows)
{
Uri TargetUri = new Uri(AppDomain.CurrentDomain.BaseDirectory + "\\Images\\Grayscale\\" + item["GrayScaleImgName"]);
BitmapImage Target = new BitmapImage(TargetUri);
if (source.IsEqual(Target))
{
IrisSystem.frmHome frm= new IrisSystem.frmHome();
frm.strFullName = item["FullName"].ToString();
frm.ShowDialog();
Form.ActiveForm.Close();
isMatchFound = true;
break;
}
Target = null;
}
if (!isMatchFound)
MessageBox.Show("Invalid Credential..","Invalid Operation");
}
File.Delete(AppDomain.CurrentDomain.BaseDirectory + "\\Images\\Temp\\" + strFileName);
}
else
MessageBox.Show("Please select image", "Login Error");
}
You need to make sure that your Bitmap objects are disposed properly.
You are not disposing the MainImg object. you need to use using {} block to make sure that objects are disposed properly.
Replace This:
Bitmap MainImg = new System.Drawing.Bitmap(txtLoginImage.Text);
Bitmap NewImage = ConvertToGrayScale(MainImg);
NewImage.Save(AppDomain.CurrentDomain.BaseDirectory + "\\Images\\Temp\\"
+ strFileName, System.Drawing.Imaging.ImageFormat.Bmp);
NewImage.Dispose();
With This:
using(Bitmap MainImg = new System.Drawing.Bitmap(txtLoginImage.Text))
using(Bitmap NewImage = ConvertToGrayScale(MainImg))
{
NewImage.Save(AppDomain.CurrentDomain.BaseDirectory + "\\Images\\Temp\\" +
strFileName, System.Drawing.Imaging.ImageFormat.Bmp);
}
EDIT:
Replace This:
BitmapImage source = new BitmapImage();
source.UriSource = SourceUri;
With This:
BitmapImage source = new BitmapImage();
source.BeginInit();
source.UriSource = SourceUri;
source.EndInit();

Speed up saving bitmap process

I have for loop to save and saveadd multiframe tiff images.If it finds a barcode in the page it save that multiframe tiff and opens new one. But it wastes memory and takes long time .How may I speed this process?
for (int i = 1; i < num_pages; i++)
{
progressBar1.Value = i;
myImg.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, i);
using (Bitmap firstImage = new Bitmap(myImg))
{
encoderParameters.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.FrameDimensionPage);
if (ReadBarcode(firstImage))
{
//önceki tifi kapat
encoderParameters.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.Flush);
xBitmap.SaveAdd(encoderParameters);
//yeni tif aç
int_file++;
encoderParameters.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.MultiFrame);
encoderParameters.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionCCITT4);
i++;
myImg.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, i);
xBitmap.Dispose();
xBitmap = null;
GC.Collect();
xBitmap = new Bitmap(myImg);
xBitmap.Save("C:\\taranan\\" + "v" + folderno + "-" + int_file.ToString() + ".TIF", encoderInfo, encoderParameters);
}
else
{
xBitmap.SaveAdd(firstImage, encoderParameters);
}
}
}
encoderParameters.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.Flush);
xBitmap.SaveAdd(encoderParameters);
xBitmap.Dispose();
xBitmap = null;
myImg.Dispose();
GC.Collect();
opened = false;
MessageBox.Show("Dosya sayısı: " + (int_file - Convert.ToInt32(fileno) + 1));
}

Microsoft Expression SDK

I'm converting mp3 to wma with expression encoder sdk 4 with the code below
A wma file is produced but it is missing the thumbnail / image / cover from the mp3 file.
using (var job = new Job())
{
var mediaItem = new MediaItem(input.FullName)
{
OutputFileName = outputFileName,
OutputFormat =
{
AudioProfile =
{
Codec = AudioCodec.Wma,
Bitrate = BitRate ?? BitRate,
Channels = 1
}
}
};
job.MediaItems.Add(mediaItem);
job.OutputDirectory = OutputDirectory;
job.CreateSubfolder = false;
job.Encode();
}
I have tried the following:
1)
mediaItem.MarkerThumbnailCodec = ImageFormat.Jpeg;
mediaItem.MarkerThumbnailJpegCompression = 0;
mediaItem.MarkerThumbnailSize = new Size(50, 50);
2)
mediaItem.ThumbnailCodec = ImageFormat.Jpeg;
mediaItem.ThumbnailEmbed = true;
mediaItem.ThumbnailJpegCompression = 50;
mediaItem.ThumbnailMode = ThumbnailMode.BestFrame;
mediaItem.ThumbnailSize = new Size(50, 50);
mediaItem.ThumbnailTime = TimeSpan.FromSeconds(0);
3)
mediaItem.OverlayFileName = #"c:\Chrysanthemum.jpg";
mediaItem.OverlayStartTime = TimeSpan.FromSeconds(0);
..but it doesn't help.
Please help me :)

Categories