Out Of Memory Exception - c#

I have function that creates an animated gif, it always worked perfectly but now when all my gifs are black and white, it gives an OutOfMemory Exception On :
e.AddFrame(Image.FromFile(imageFilePaths[i]));
My Function :
public void MakeGif(string sourcefolder, string destinationgif)
{
IsGifing = true;
string path = MainForm.RootDirectory;
String[] imageFilePaths = Directory.GetFiles(path);
String outputFilePath = MainForm.RootDirectory + #"\Final.gif";
AnimatedGifEncoder e = new AnimatedGifEncoder();
e.Start(outputFilePath);
e.SetDelay(300);
//-1:no repeat,0:always repeat
e.SetRepeat(0);
for (int i = 0, count = imageFilePaths.Length; i < count; i++)
e.AddFrame(Image.FromFile(imageFilePaths[i]));
e.Finish();
IsGifing = false;
}
AddFrame Function :
public bool AddFrame(Image im)
{
if ((im == null) || !started)
{
return false;
}
bool ok = true;
try
{
if (!sizeSet)
{
// use first frame's size
SetSize(im.Width, im.Height);
}
image = im;
GetImagePixels(); // convert to correct format if necessary
AnalyzePixels(); // build color table & map pixels
if (firstFrame)
{
WriteLSD(); // logical screen descriptior
WritePalette(); // global color table
if (repeat >= 0)
{
// use NS app extension to indicate reps
WriteNetscapeExt();
}
}
WriteGraphicCtrlExt(); // write graphic control extension
WriteImageDesc(); // image descriptor
if (!firstFrame)
{
WritePalette(); // local color table
}
WritePixels(); // encode and write pixel data
firstFrame = false;
}
catch (IOException e)
{
ok = false;
}
return ok;
}

Documentation for Image.FromFile says that it will throw OutOfMemoryException if the file does not contain a valid image, or if the image is in a format that GDI+ doesn't support.
What happens if you rewrite your code to:
for (int i = 0, count = imageFilePaths.Length; i < count; i++)
{
var img = Image.FromFile(imageFilePaths[i]);
e.AddFrame(img);
}
If you get the exception on the call to Image.FromFile, it's because your image can't be loaded.

I don't know the details, but this doesn't look write. There are no 'usings' so you possibly aren't disposing of resources.

Related

Save a bitmap at same folder as the original with a set name

I want to make a program that loads a file by input in console, convert the picture into greyscale, negative and blurred. Then I want to make copys of the converted picture in the same folder as the original with extra text at the filename (ex: picture_negative.jpg). My problem is that i can't figure out how i save the pictures in the save folder with the extra text.
This is my first month with programming so im not very experienced.
static void Main(string[] args)
{
Bitmap picture;
try
{
Console.Write("Write the file you want to edit ");
picture = new Bitmap(Console.ReadLine=
}
catch (ArgumentNullException)
{
Console.WriteLine("No picture choosen");
return;
}
catch (ArgumentException)
{
Console.WriteLine("error");
return;
}
ConvertAlgoritms.ConvertAlgoritms.MakePictureGreyScale(picture);
ConvertAlgoritms.ConvertAlgoritms.MakePictureNegative(picture);
ConvertAlgoritms.ConvertAlgoritms.MakePictureBlurred(picture);
}
Example of the class
public class ConvertAlgoritms
{
public static Bitmap MakePictureGreyScale(Bitmap originalPicture)
{
Bitmap newPicture = new Bitmap(originalPicture);
int x, y;
for (x = 0; x < newPicture.Width; x++)
{
for (y = 0; y < newPicture.Height; y++)
{
Color pixel = newPicture.GetPixel(x, y);
int r = pixel.R;
int g = pixel.G;
int b = pixel.B;
int greyScale = (r + g + b) / 3;
newPicture.SetPixel(x, y, Color.FromArgb(greyScale, greyScale, greyScale));
}
}
return newPicture;
}
}
You have Bitmap.Save().
First, you must save the entered file name in the console into a variable.
Then, you can append a string to this name before the extension.
Example:
Console.Write("Write the file you want to edit ");
Filename = Console.ReadLine();
picture = new Bitmap(Filename);
string NewFilename = Path.GetFileNameWithoutExtension(Filename)
+ StrToAppend
+ Path.GetExtension(Filename);
picture.Save(Newfilename, picture.RawFormat);
You need to pick up the returned image e.g.:
var greyscalePicture = ConvertAlgoritms.ConvertAlgoritms.MakePictureGreyScale(picture);
Then you can just save it:
greyscalePicture.Save("Fancynewfilename.jpg", ImageFormat.Jpeg);
This assumes that your file format is JPEG.
To generate the new filename you need to keep a reference to the old one.
var originalFilename = Console.ReadLine();
var picture = new Bitmap(originalFilename);
Then you can build the filenames using the Path class as #Corak suggests.

Looping through stream data

I'm writing a program that uses a fingerprint reader. I have stored the fingerprint data in an array [arr]. Unfortunately, only the first value is read i.e [0]. So only one finger is detected and the rest are ignored but if I place a specific number in the array e.g 2. It works fine for that value alone:
Here's my code:
for (int x = 0; x < (arr.Length - 1); x++)
{
byte[] fpbyte = GetStringToBytes(arr[x]);
Stream stream = new MemoryStream(fpbyte);
Data.Templates[x] = new DPFP.Template(stream);
}
foreach (DPFP.Template template in Data.Templates)
{
// Get template from storage.
if (template != null)
{
// Compare feature set with particular template.
ver.Verify(FeatureSet, template, ref res);
Data.IsFeatureSetMatched = res.Verified;
Data.FalseAcceptRate = res.FARAchieved;
if (res.Verified)
MessageBox.Show("Yes");
break; // success
}
}
if (!res.Verified)
Status = DPFP.Gui.EventHandlerStatus.Failure;
MessageBox.Show("No");
Data.Update();
You unconditionally break from your loop, whether verified or not.
Your code should read :
if (res.Verified) {
MessageBox.Show("Yes");
break; // success
}
This is a good example why good coding practice suggests always having the brackets, even for a one line conditional effect, as the error would have been much more obvious.
Similarly you should have written
if (!res.Verified) {
Status = DPFP.Gui.EventHandlerStatus.Failure;
MessageBox.Show("No");
}
at the end of your snippet.
Thanks to Dragonthoughts, I made the following changes and the code works just fine:
for (int x = 0; x < (arr.Length - 1); x++)
{
byte[] fpbyte = GetStringToBytes(arr[x]);
using (Stream stream = new MemoryStream(fpbyte))
{
Data.Templates[x] = new DPFP.Template(stream);
// Get template from storage.
if (Data.Templates[x] != null)
{
// Compare feature set with particular template.
ver.Verify(FeatureSet, Data.Templates[x], ref res);
Data.IsFeatureSetMatched = res.Verified;
Data.FalseAcceptRate = res.FARAchieved;
if (res.Verified)
{
status.Text = "Verified";
break; // success
}
}
}
}
if (!res.Verified)
{
Status = DPFP.Gui.EventHandlerStatus.Failure;
status.Text = "Unverified";
}
Data.Update();

Read all pages from PDF c#

I want to read all pages of my PDF and save them as a images, so far what I am doing is only getting me the page defined 0 = 1 first etc .. Is there a chance that I can define a range ?
static void Main(string[] args)
{
try
{
string path = #"C:\Users\test\Desktop\pdfToWord\";
foreach (string file in Directory.EnumerateFiles(path, "*.pdf")) {
using (var document = PdfiumViewer.PdfDocument.Load(file))
{
int i = 1;
var image = document.Render(0,300,300, true);
image.Save(#"C:\Users\test\Desktop\pdfToWord\output.png", ImageFormat.Png);
}
}
}
catch (Exception ex)
{
// handle exception here;
}
if your document-object gives you the pagecount,
you could replace
int i = 1;
var image = document.Render(0,300,300, true);
image.Save(#"C:\Users\test\Desktop\pdfToWord\output.png", ImageFormat.Png);
by
for(int index = 0; index < document.PageCount; index++)
{
var image = document.Render(index,300,300, true);
image.Save(#"C:\Users\test\Desktop\pdfToWord\output"+index.ToString("000")+".png", ImageFormat.Png);
}

Playing 30 sound effects at the same time repeatedly

I'm trying to play about 30 piano notes at the same time in my XNA application on Windows Phone 7.
I have imported and loaded the wave files like below
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
sound3 = Content.Load<SoundEffect>("1");
sound5 = Content.Load<SoundEffect>("3");
sound6 = Content.Load<SoundEffect>("4");
sound7 = Content.Load<SoundEffect>("5");
sound8 = Content.Load<SoundEffect>("6");
}
Every sound effect file is less than a second, so I'm trying to play all of them at the same time. I play them using a for loop which runs every second.(So at every loop 30 sounds will be played then it goes on and plays the same 30 sounds each second)
It works fine for a few seconds but suddenly it stops playing any sound (The loop is still working) then again starts working for once or twice and again stops working . It also sometimes makes some bad noises as if the audio system cant support too many sounds to be play at a time.
I'm not sure how I can solve the problem , if its a buffer problem or threads.
Nico Schertler is right! I've faced the same problem and fixed it by managing instances. Normally when you play soundeffect you always get the instance! By default you have to hope XNA/Monogame will care about it, but it doesn't. When you have to many live instances (even stopped, you get breaks, noise, even silence.
I hold rectangular array for all my sound effects with up to 4 instance for each, and if I have instances of a sound I want to play instead of creating I stop the oldest (by timestamp), play it and remember the current timestamp.
See the following code:
private const int MAX_INST_OF_ONE_SOUND = 4;
private SoundEffectInstance[][] sndInstArray = null;
private float[][] sndInstTimes = null;
public init()
{
sndArray = new SoundEffect[SoundsSchema.sounds.Length];
sndInstArray = new SoundEffectInstance[SoundsSchema.sounds.Length][];
sndInstTimes = new float[SoundsSchema.sounds.Length][];
for (int i = 0; i < SoundsSchema.sounds.Length; i++)
{
try
{
sndArray[i] = content.Load<SoundEffect>(SoundsSchema.sounds[i]);//SoundsSchema is string list holder class
}
catch (System.Exception)
{
}
sndInstArray[i] = new SoundEffectInstance[MAX_INST_OF_ONE_SOUND];
sndInstTimes[i] = new float[MAX_INST_OF_ONE_SOUND];
}
}
private SoundEffectInstance getValidInstance(int sound)
{
if (sound < 0 || sound > sndInstArray.Length)
return null;
SoundEffectInstance inst = null;
for (int i = 0; i < MAX_INST_OF_ONE_SOUND; i++)
{
if (sndInstArray[sound][i] == null || (sndInstArray[sound][i] != null && sndInstArray[sound][i].IsDisposed))
{
sndInstArray[sound][i] = sndArray[sound].CreateInstance();
sndInstTimes[sound][i] = MyEngine.CurTime;
inst = sndInstArray[sound][i];
break;
}
}
if (inst == null)
{
float min_time = float.MaxValue;
int ind = -1;
for (int i = 0; i < MAX_INST_OF_ONE_SOUND; i++)
{
if (sndInstArray[sound][i] != null && sndInstTimes[sound][i] < min_time)
{
min_time = sndInstTimes[sound][i];
ind = i;
}
}
if (ind == -1)
ind = 0;
if (sndInstArray[sound][ind].IsDisposed)
sndInstArray[sound][ind] = sndArray[sound].CreateInstance();
else
{
try
{
sndInstArray[sound][ind].Stop();
}
catch
{}
}
sndInstTimes[sound][ind] = MyEngine.CurTime;
inst = sndInstArray[sound][ind];
}
return inst;
}
public virtual void playSound(int sound, float volume, float panoram, bool loop)
{
if (sound < 0 || sound > sndArray.Length)
return null;
if (!mMuted && mVolume > 0)
{
SoundEffectInstance sndinst = getValidInstance(sound);
if (sndinst == null)
return null;
try
{
sndinst.IsLooped = loop;
sndinst.Pan = panoram;
sndinst.Volume = mVolume * vol;
sndinst.Play();
}
catch
{
}
}
}

what is the meaning of this error "out of memory" when using picturebox1.Image equal to image FromFile(fileName)?

I have a problem now with displaying an image from an exist file ...
try
{
bool EndFlag = false;
string fileLoc = #"../../../../samples/jpeg_" + DateTime.Now.ToString("yyyyMMdd_hhmmss") + ".jpg";
//Create a file Stream to save the body of the JPEG File content.
FileStream fs = null;
fs = new FileStream(fileLoc, FileMode.OpenOrCreate, FileAccess.Write);
do
{
ReadJpegFileCommand();
CamPort.DiscardOutBuffer();
CamPort.DiscardInBuffer();
for (int i = 0; i < 5; i++)
header[i] = (byte)CamPort.ReadByte();
if (((int)header[0] == 0x76) && (header[1] == 0x00) && (header[2] == 0x32) && (header[3] == 0x00) && (header[4] == 0x00))
{
for (int i = 0; i < 32; i++)
ImageBody[i] = (byte)CamPort.ReadByte();
/*
* writing the bytes that have been read till now to a file
*/
fs.Write(ImageBody, 0, ImageBody.Length);
for (int i = 1; i < ImageBody.Length; i++) // check if reached to the last two bytes(FF D9) of the body to stop reading the body.
{
if ((ImageBody[i - 1] == 0xFF) && (ImageBody[i - 0] == 0xD9))
{
EndFlag = true;
MessageBox.Show("FFD9 has been received");
OneSnap.Image =(Bitmap)System.Drawing.Image.FromStream(fs);
fs.Close();
}
}
}
else
{
MessageBox.Show("Error,Try again"); // The first 5 bytes does not match the header
}
for (int i = 0; i < footer.Length; i++)
{
footer[i] = (byte)CamPort.ReadByte();
}
// update the starting address
M += (UInt16)ImageBody.Length;
//Progress.PerformStep();
}while(!EndFlag);
}
catch (System.Exception ex) { MessageBox.Show(ex.Message); }
When I have used this statements :
OneSnap.Image =(Bitmap)System.Drawing.Image.FromStream(fs);
fs.Close();
I had this error : "Parameter is not valid"
but when I've tried with alternative way and replaced the previous statements by ::
fs.Close();
OneSnap.Image =(Bitmap)System.Drawing.Image.FromFile(fileLoc);
I showed the image in the picture box .. but then when I have executed the program more I had this error :: " Out of memory " and couldn't see the image in the picture box (OneSnap) >>> How to solve this ??
sample :: ( this image has been captured by link Sprite Jpeg Camera )
Looks like the file you created is not a valid picture, so can't be converted to a Bitmap.
See the official docuemtation:
Exception Condition
-------------------------------
OutOfMemoryException The file does not have a valid image format.
-or-
GDI+ does not support the pixel format of the file.
Can't see a way to "fix" this, but you can verify by trying to view the file in picture viewer; if you can view it then you might need something more complex than what System.Drawing offers.
Edit: might be easier than any of us imagined. Try changing the order of your lines:
fs.Close();
OneSnap.Image =(Bitmap)System.Drawing.Image.FromStream(fs);
Might be that while the stream is open, the Bitmap internal code can't read from the file.
Another approach is using MemoryStream instead. For this, first add a List to store all the bytes:
List<byte> arrAllBytes = new List<byte>();
Now instead of this line:
fs.Write(ImageBody, 0, ImageBody.Length);
Have this code:
arrAllBytes.AddRange(ImageBody);
And finally:
MemoryStream stream = new MemoryStream(arrAllBytes.ToArray())
OneSnap.Image = System.Drawing.Image.FromStream(stream);

Categories