Visual C++, System Argument Exception in System Drawing (Windows Form) - image

This error shows up when run the program and try to load an image:
A first chance exception of type 'System.ArgumentException' occurred in System.Drawing.dll
An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll
Additional information: The parameter is invalid.
Here is my code:
Basically, there is a numericUpDown, a button, an openFileDialog and a pictureBox. The user changes the numericUpDown's value, depending on which picture he wants to load (the user doesn't have to open the openFileDialog). For example, if the user chooses "3" as a value for the numericUpDown, the FileName of the openFileDialog will be:
Public:
void Set_FilePath()
{
int n = (int)numericUpDown1->Value;
switch (n)
{
case 1: openFileDialog1->FileName = "C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg"; break;
case 2: openFileDialog1->FileName = "C:\Users\Public\Pictures\Sample Pictures\Desert.jpg"; break;
case 3: openFileDialog1->FileName = "C:\Users\Public\Pictures\Sample Pictures\Hydrangeas.jpg"; break;
case 4: openFileDialog1->FileName = "C:\Users\Public\Pictures\Sample Pictures\Jellyfish.jpg"; break;
case 5: openFileDialog1->FileName = "C:\Users\Public\Pictures\Sample Pictures\Koala.jpg"; break;
case 6: openFileDialog1->FileName = "C:\Users\Public\Pictures\Sample Pictures\Lighthouse.jpg"; break;
case 7: openFileDialog1->FileName = "C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg"; break;
case 8: openFileDialog1->FileName = "C:\Users\Public\Pictures\Sample Pictures\Tulips.jpg"; break;
}
}
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
Bitmap^ myImage;
Set_FilePath();
myImage = gcnew Bitmap( openFileDialog1->FileName );
pictureBox1->SizeMode = PictureBoxSizeMode::StretchImage;
pictureBox1->Image = dynamic_cast <Image^> (myImage);
}
My attempt to fix it:
I thought that i didn't copy the directions of the images correctly. So i changed the code to:
if(openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK)
{
MessageBox::Show(openFileDialog1->FileName);
myImage = gcnew Bitmap( openFileDialog1->FileName );
pictureBox1->SizeMode = PictureBoxSizeMode::StretchImage;
pictureBox1->Image = dynamic_cast <Image^> (myImage);
}
This is working perfectly. Also, a messagebox that shows the filename of openFileDialog is appeared... The directions of the images that are correct... I don't know what is wrong with my program. The problem is that i don't want the openFiledialog to be appeared.
(I am using Visual Studio C++ 2010, the application is made in windows form), Any help would be appreciated.
Thanks..

Exceptions raised by the Image and Bitmap classes are not very informative. You can get an "The parameter is invalid" exception for several reasons. It could be an image file that's corrupted, not that likely in your case since you are using stock Windows image files. It can also be caused by an image that's too large to fit in the available virtual memory address space. You'd like an OutOfMemoryException but GDI+ is goofy about it.
That's the more likely cause, your program is pretty likely to bite the dust like that when you run it for a while. Images can require a lot of unmanaged virtual memory to store their pixel data. And that should be released when you no longer use the image. The garbage collector will do that for you, but it isn't all that quick about it. Certainly an issue with the Bitmap class, it uses very little GC heap so isn't terribly likely to trigger a garbage collection often enough to keep you out of trouble.
Which is why it implements the IDisposable interface. The Dispose() method gets that memory released early. You are not calling it.
You'll need to fix that in your code, like this:
delete picureBox1->Image;
try {
myImage = gcnew Bitmap( openFileDialog1->FileName );
pictureBox1->Image = myImage;
}
catch (Exception^ ex) {
pictureBox1->Image = nullptr;
MessageBox::Show(ex->Message);
}
Note the added delete operator call, that's the one that calls IDisposable::Dispose(). It gets rid of the old image, the one you don't need anymore because you are going to display another image. The try/catch ensures that your program keeps running when the chips are down, dealing with a bad image file or a monster one that just can't fit in available memory. The kind that you deal with by targeting x64 so you get a 64-bit program.

Related

uploaded image orientation issues

i've been looking for a solution for the whole day but don't seem to be able to find a proper solution.
The problem is (i think) quite simple. When an image is uploaded on my page it is then displayed in an img element. Now for some reason it is rotated by itself from portrait to landscape.
I cut the middle man and connected the img tag to the path.
Problem persists.
If i open it in ps and save it as a new jpeg it is fixed but that is not a viable choice since images will be uploaded directly from clients.
In not other program (ps, paint, photos, photos3d) does that issue exist
In my digging around i found that that is propably caused from the exif data of the image.
Everything else ignores that data, or reads it correctly idk.
Can anyone please tell me how to fix that?
I tried adding image-orientation:0deg and image-orientation:from-image to no result.
Also, just for my sanity's sake, does anyone know WHY this would be a problem?
EDITThis does not happen on firefox. That being said i cannot force everyone to avoid chrome
Thanks in advance
Ok so i looked everywhere and found some ways to rotate the image client side and added css to make it look legit. Then i realized that all that was wasted since it would cause the image to overrotate in browsers that displayed it correctly.
Ended up taking it to server side and fixing it there (rotating based on exif and the removing the exif data)
I will include the controller code
public JsonResult NormalizeOrientation(HttpPostedFileBase file)
{
Image img = Image.FromStream(file.InputStream);
if (Array.IndexOf(img.PropertyIdList, 274) > -1)
{
var orientation = (int)img.GetPropertyItem(274).Value[0];
switch (orientation)
{
case 1:
// No rotation required.
break;
case 2:
img.RotateFlip(RotateFlipType.RotateNoneFlipX);
break;
case 3:
img.RotateFlip(RotateFlipType.Rotate180FlipNone);
break;
case 4:
img.RotateFlip(RotateFlipType.Rotate180FlipX);
break;
case 5:
img.RotateFlip(RotateFlipType.Rotate90FlipX);
break;
case 6:
img.RotateFlip(RotateFlipType.Rotate90FlipNone);
break;
case 7:
img.RotateFlip(RotateFlipType.Rotate270FlipX);
break;
case 8:
img.RotateFlip(RotateFlipType.Rotate270FlipNone);
break;
}
// This EXIF data is now invalid and should be removed.
img.RemovePropertyItem(274);
}
MemoryStream ms = new MemoryStream();
img.Save(ms, ImageFormat.Jpeg);
return Json(new { base64imgage = Convert.ToBase64String(ms.ToArray()) }
, JsonRequestBehavior.AllowGet);
}

Speech Recognition does not trigger EventHandler in C++/CLI DLL

I have a TS3 plugin in creation right here, which uses
System::Speech::Recognition for its SpeechRecognitinEngine. Now, I create an EventHandler for the SpeechRecognized event.
Well, my logging (and the actions of the plugin - None) tell me, that the Event is actually never triggered, even if you start and stop talking with the (somewhat) valid (parts of the) grammar.
I have no idea why this is. It happens in a DLL written in C++ CLI.
Now, my theory was that DLLs do not support event handerls... Might that be possible?
void recogn_speech() {
uint64 schid = ts3Functions.getCurrentServerConnectionHandlerID();
SpeechRecognitionEngine^ recognizer = gcnew SpeechRecognitionEngine();
System::Speech::Recognition::Grammar^ g = assembleGrammar();
recognizer->LoadGrammar(g);
recognizer->SetInputToDefaultAudioDevice();
char pluginPath[PATH_BUFSIZE];
ts3Functions.getPluginPath(pluginPath, PATH_BUFSIZE, pluginID);
String^ a = gcnew String(pluginPath);
a = a + "vctest_cpp_ts3\\signal_vc_start.wav";
char* newPath = (char*)(void*)Marshal::StringToHGlobalAnsi(a);
ts3Functions.playWaveFile(schid, newPath);
Marshal::FreeHGlobal((IntPtr)newPath);
recognizer->SpeechRecognized +=
gcnew EventHandler<SpeechRecognizedEventArgs^>(this, &tsapi::sre_SpeechRecognized);
}
void sre_SpeechRecognized(Object^ sender, SpeechRecognizedEventArgs^ e)
{
uint64 schid = ts3Functions.getCurrentServerConnectionHandlerID();
String^ recognRes = e->Result->Text->ToString();
interpretCommand(recognRes);
}
Full Sourcecode on
GitHub
Your event handler looks correct. There's no issue with having events & event handlers across DLLs: It's all managed code, the DLL boundary doesn't matter here.
However, there is one possible issue:
void recogn_speech() {
...
SpeechRecognitionEngine^ recognizer = gcnew SpeechRecognitionEngine();
...
}
You might want to save your SpeechRecognitionEngine object somewhere so it doesn't get garbage collected.
Also, you may want to switch to the more C++-style of having class definitions in .h files, and implementations in .cpp files. As your code gets more complex and the classes need to refer to each other, having everything in one file will start to become an issue.

CreateIconFromResource return NULL and UI crashed after being called thousands of times

Anybody got this problem, anyway I didn't find an answer. The code is simple:
void CbDlg::OnBnClickedOk()
{
for(int i=0; i<1000; i++)
{
HRSRC hRes = ::FindResource(NULL, MAKEINTRESOURCE(IDR_MAINFRAME), RT_GROUP_ICON);
HGLOBAL hResLoad = ::LoadResource(NULL, hRes);
BYTE* pIconBytes = (BYTE*)::LockResource(hResLoad);
int nId = ::LookupIconIdFromDirectory(pIconBytes, TRUE);
hRes = ::FindResource(NULL, MAKEINTRESOURCE(nId), RT_ICON);
DWORD read = ::SizeofResource(NULL ,hRes);
hResLoad = ::LoadResource(NULL, hRes);
pIconBytes = (BYTE*)::LockResource(hResLoad);
if(pIconBytes != NULL)
{
HICON hIcon = ::CreateIconFromResource(pIconBytes, read, TRUE, 0x00030000);
DWORD e = ::GetLastError();
if(hIcon != NULL)
{
::DestroyIcon(hIcon);
}
}
}
}
If I click the Ok button four times (On my computer), CreateIconFromResource start to return NULL (It worked fine before and I could even draw out the icon). As to the GetLastError, it's always return 6 whatever CreateIconFromResource return NULL or not.
When this problem happened, if I drag the title bar to move, UI crashed, see the pictrue.
Of course you can understand this piece of code is just a demo, my real business need to call CreateIconFromResource thousands of times just like this.
UPDATE:
According to Hans' suggestion, I keep tracking the Handles/USER Objects/GDI objects, and found that USER Objects grows 1000 and GDI objects grows 2000 against each clicking to OK button (handles didn't grow), and GDI objects is 9999 when problem happens. But how to release them correctly, when I finish to use? I didn't use that much at one time, but need to load, release, load again, release again... Just like this demo. As MSDN document, I called DestroyIcon for every HICON. What else do I need to do, to finally release the USER/GDI objects?
I found the answer. The success or failure is all due to MSDN.
It says:
"The CreateIconFromResource function calls CreateIconFromResourceEx passing LR_DEFAULTSIZE|LR_SHARED as flags" AND "Do not use this function(DestroyIcon) to destroy a shared icon"
But It also says:
"When you are finished using the icon, destroy it using the DestroyIcon function" in CreateIconFromResource's document.
Actually, the second statement is WRONG.
So, the solution is, using CreateIconFromResourceEx without LR_SHARED, and DestroyIcon every HICON after using.

MFC Printing Issue - Access Violation Exception

I'm having an issue with some MFC printing code lately. To describe the issue at a high level, we're getting problems when we try to print the same document twice. (Really, it doesn't have to be the SAME document. It seems that it happens when two documents are printed and the child window isn't destroyed and created between them.) The first time, the document prints fine. The second time, the program crashes with an uncaught exception.
This also only started happening after a recent upgrade. This is code that I've literally never touched. It worked fine in version 5 when we were using VS2005 and MFC8. But then, when we upgraded to VS2008 and MFC9, this started happening.
Here's the problem code:
void CReportWnd::OnPrint()
{
CDC dc;
CPrintDialog dlg (FALSE);
CPrintDialog defaults(FALSE);
DEVMODE *ldev_printinfo;
int li_first = 0;
int li_last;
int ret = defaults.GetDefaults();
ldev_printinfo = defaults.GetDevMode();
//ldev_printinfo->dmOrientation = DMORIENT_LANDSCAPE;
dc.Attach (defaults.GetPrinterDC ());
dc.ResetDC(ldev_printinfo);
PROPrint(1, NULL, &dc, NULL, &li_last, true);
dlg.m_pd.hDevMode = ldev_printinfo;
dlg.m_pd.Flags &= ~PD_NOPAGENUMS;
dlg.m_pd.nMinPage = 1;
dlg.m_pd.nFromPage = 1;
dlg.m_pd.nMaxPage = li_last;
dlg.m_pd.nToPage = li_last;
if (dlg.DoModal () == IDOK) {
dc.DeleteDC();
dc.Detach();
dc.Attach (dlg.GetPrinterDC ());
} else {
return;
}
//Set up document info (need to set the name)
DOCINFO di;
::ZeroMemory (&di, sizeof (DOCINFO));
di.cbSize = sizeof (DOCINFO);
di.lpszDocName = "Report";
if(dc.StartDoc(&di) <= 0) {
return;
}
if(dlg.PrintRange()) {
li_first = dlg.m_pd.nFromPage - 1;
li_last = dlg.m_pd.nToPage - 1;
}
//Now do the actual print job to the printing device
PROPrint(1, NULL, &dc, &li_first, &li_last, false);
}
On the int ret = ... line near the top is where the exception is thrown. GetDefaults() throws an access violation exception. But again, only the second time that this function is called. It seems to me like it's some sort of resource issue. Like a resource isn't being freed and allocated properly. But I'm so inexperienced with printing that it could be anything.
If anybody could offer any kind of help, I would really appreciate it.
Also, yes, I know that I can just catch the exception. My issue is, how do I handle the exception and still print the document?
EDIT:
It seems as if our program is having this issue in multiple places, not just with this particular set of code. It makes me think that the issue might not be in this code specifically. I'm working on it now and I kind of have to get it fixed, so when I figure out the solution, I'll be sure to post back. Until then, I'm always open to suggestions.
Not sure, but could it be because the code is deleting the default device context associated with the default printer? Try removing the dc.DeleteDC() line to give you:
if (dlg.DoModal() == IDOK)
{
dc.Detach();
dc.Attach(dlg.GetPrinterDC());
}
else
return;

OutOfMemoryException in Image Resizing

We are using a .net dll (http://imageresizing.net/download) for imageresizing on runtime. It works perfectly. However, it happen after some time (between 1-7 days) that system started to raise exception in the even viewer:
Exception information:
Exception type: OutOfMemoryException
Exception message: Insufficient memory to continue the execution of the program.
And after that exception the website usually stop working with the error throwing "System.OutOfMemoryException".
And if we "recycle" the application pool in which the website is running, it clears the problem and website get back to normal immediately without any code change.
Before imagereiszing dll, we were using our custom code and same problem happen with that too. Following is the code.
private Bitmap ConvertImage(Bitmap input, int width, int height, bool arc)
{
if (input.PixelFormat == PixelFormat.Format1bppIndexed ||
input.PixelFormat == PixelFormat.Format4bppIndexed ||
input.PixelFormat == PixelFormat.Format8bppIndexed)
{
Bitmap unpackedBitmap = new Bitmap(input.Width, input.Height);
Graphics g = Graphics.FromImage(unpackedBitmap);
g.Clear(Color.White);
g.DrawImage(input, new Rectangle(0,0,input.Width, input.Height));
g.Dispose();
input = unpackedBitmap;
}
double aspectRatio = (double)input.Height / (double)input.Width;
int actualHeight = CommonMethods.GetIntValue(Math.Round(aspectRatio * width, 0));
Bitmap _imgOut;
if (actualHeight > height)
{
ResizeImage resizeImage = new ResizeImage(width, actualHeight, InterpolationMethod.Bicubic);
Bitmap _tempBitmap = resizeImage.Apply(input);
Bitmap _croppedBitmap = new Bitmap(width, height);
Graphics _crop = Graphics.FromImage(_croppedBitmap);
_crop.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
_crop.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
_crop.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
_crop.DrawImageUnscaledAndClipped(_tempBitmap, new Rectangle(0, 0, width, height));
_crop.Dispose();
_imgOut = _croppedBitmap;
}
else
{
ResizeImage resizeImage = new ResizeImage(width, height, InterpolationMethod.Bicubic);
_imgOut = resizeImage.Apply(input);
}
// Draw the arc if it has been requested
if (arc)
{
Graphics _arc = Graphics.FromImage(_imgOut);
_arc.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
_arc.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
_arc.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
_arc.DrawArc(new Pen(Color.White, 24), new Rectangle(-13, -13, 50, 50), 180, 90);
_arc.Dispose();
}
// job done
return _imgOut;
}
We are resizing image like: www.mysite.com/images/myimage.jpg?width=196&height=131
Looking forward.
Farrukh
When you encounter an OutOfMemoryException (regardless of where it occurs), it can be caused by a memory leak anywhere in the application. Having debugged dozens of these instances with WinDbg, I've never found any that ended up being due to a bug in http://imageresizing.net.
That said, there's an easy way to determine whether it is a problem with http://imageresizing.net or not; create a separate application pool and subfolder application in IIS for your images and image resizing. Install nothing there except the image resizer. Next time you encounter the error, log on to the server and find out which w3wp.exe instance is responsible for the massive memory usage.
If it's in the ImageResizer app pool, go collect your $20-$50 bug bounty from http://imageresizing.net/support. If not, you need to figure out where you're leaking stuff in your main application.
If you're working with System.Drawing anywhere else in the app, that's the first place to look. Check your code against this list of pitfalls.
If you're positive you're disposing of every System.Drawing.* instance in a using or finally clause, then read this excellent article a few times to make sure you're not failing on any of the basics, then dig in with DebugDiag and/or WinDBG (see bottom of article).

Resources