This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Troubleshooting .NET “Fatal Execution Engine Error”
My code is throwing a Fatal Execution Error. The exact error is this:
The runtime has encountered a fatal error. The address of the error
was at 0xed40646c, on thread 0x2044. The error code is 0xc0000005.
This error may be a bug in the CLR or in the unsafe or non-verifiable
portions of user code. Common sources of this bug include user
marshaling errors for COM-interop or PInvoke, which may corrupt the
stack.
I'm not using unsafe user code as far as I know.
The code which is causing the issue is this one:
WebClient client = new WebClient();
string pageHtml = client.DownloadString(url);
browser.ScriptErrorsSuppressed = true;
browser.DocumentText = pageHtml;
do
{
Application.DoEvents();
} while (browser.ReadyState != WebBrowserReadyState.Complete); //CRASH OCCURS HERE
Now here's the kicker. This code is beign run on a loop. Every so often, it gives this error. Sometimes its on the 1000th run. Last time it was on the 5545th run. It seems to be very random indeed.
How do I solve this problem? Or how can I get more information to solve it?
My solution is based on How to wait until WebBrowser is completely loaded in VB.NET?
What u have to do is to add bool _pageReady variable to Completed event.
void web_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var urlCurrent = e.Url.ToString();
var browser = (WebBrowser)sender;
if (!(urlCurrent.StartsWith("http://") || urlCurrent.StartsWith("https://")))
{
// in AJAX
}
if (e.Url.AbsolutePath != browser.Url.AbsolutePath)
{
// IFRAME
}
else
{
// DOCUMENT IS LOADED 100%
Debug.WriteLine("DocumentCompleted " + DateTime.Now.TimeOfDay.ToString());
_pageReady = true; // Here it goes!!!! :)
try
{
mshtml.IHTMLDocument2 docs2 = (mshtml.IHTMLDocument2)web.Document.DomDocument;
mshtml.IHTMLDocument3 docs3 = (mshtml.IHTMLDocument3)web.Document.DomDocument;
mshtml.IHTMLElement2 body2 = (mshtml.IHTMLElement2)docs2.body;
mshtml.IHTMLElement2 root2 = (mshtml.IHTMLElement2)docs3.documentElement;
// Determine dimensions for the image; we could add minWidth here
// to ensure that we get closer to the minimal width (the width
// computed might be a few pixels less than what we want).
int width = Math.Max(body2.scrollWidth, root2.scrollWidth);
int height = Math.Max(root2.scrollHeight, body2.scrollHeight);
//get the size of the document's body
Rectangle docRectangle = new Rectangle(0, 0, width, height);
web.Width = docRectangle.Width;
web.Height = docRectangle.Height;
//if the imgsize is null, the size of the image will
//be the same as the size of webbrowser object
//otherwise set the image size to imgsize
Rectangle imgRectangle;
if (imgsize == null) imgRectangle = docRectangle;
else imgRectangle = new System.Drawing.Rectangle() { Location = new System.Drawing.Point(0, 0), Size = imgsize.Value };
//create a bitmap object
__Bitmap = new Bitmap(imgRectangle.Width, imgRectangle.Height);
//Rectangle resolution = Screen.PrimaryScreen.Bounds;
//__Bitmap.SetResolution(resolution.Width, resolution.Height);
//get the viewobject of the WebBrowser
IViewObject ivo = web.Document.DomDocument as IViewObject;
using (Graphics g = Graphics.FromImage(__Bitmap))
{
//get the handle to the device context and draw
IntPtr hdc = g.GetHdc();
ivo.Draw(1, -1, IntPtr.Zero, IntPtr.Zero,
IntPtr.Zero, hdc, ref imgRectangle,
ref docRectangle, IntPtr.Zero, 0);
g.ReleaseHdc(hdc);
}
//var randomPart = System.IO.Path.GetRandomFileName();
//__Bitmap.Save(#"D:\t" + randomPart + ".png");
if (CropRectangle != null)
{
if (CropRectangle.Width > 0 && CropRectangle.Height > 0)
{
Bitmap bmpCrop = __Bitmap.Clone(CropRectangle, __Bitmap.PixelFormat);
__Bitmap = bmpCrop;
}
}
//__Bitmap.Save(#"D:\cropped" + randomPart + ".png");
bitmapPointer = __Bitmap.GetHbitmap();
}
catch
{
//System.Diagnostics.Process.GetCurrentProcess().Kill();
}
}
}
and also to do something like
public void HtmlCapture2()
{
try
{
if (web == null)
web = InitWebBrowser();
web.Navigate(_navigateURL);
try
{
while (_pageReady == false) // YEAH!!!!!! IT IS WORKING!!!!
{
System.Windows.Forms.Application.DoEvents();
}
//Thread.Sleep(WaitForWebsite); --- It works but....
//while (web.ReadyState != WebBrowserReadyState.Complete) --- it gives an ERROR
// System.Windows.Forms.Application.DoEvents();
}
catch (Exception)
{
}
}
catch (Exception)
{
}
}
Related
First time trying to render something and I have big troubles... I am using DirectN library and SwapChainSurface class from KlearTouch.MediaPlayer. I am trying to render BGRA32 frame using D3D11Device.
For this I have slightly modified OnNewSurfaceAvailable:
public void OnNewSurfaceAvailable2(Action<ID3D11Device, ID3D11DeviceContext> updateSurface)
{
if (rendering)
{
return;
}
try
{
if (this.swapChain is null || swapChainComObject is null)
{
return;
}
swapChainComObject.GetDesc(out var swapChainDesc).ThrowOnError();
if (swapChainDesc.BufferDesc.Width != PanelWidth || swapChainDesc.BufferDesc.Height != PanelHeight)
{
swapChainComObject.ResizeBuffers(2, PanelWidth, PanelHeight, DXGI_FORMAT.DXGI_FORMAT_UNKNOWN, 0).ThrowOnError();
}
var device = swapChain.Object.GetDevice1().Object.As<ID3D11Device>();
device.GetImmediateContext(out var context);
// context.ClearRenderTargetView(renderTargetView.Object, new []{0f, 1f, 1f, 1f});
updateSurface(device, context);
swapChainComObject.Present(1, 0).ThrowOnError();
}
catch (ObjectDisposedException)
{
Reinitialize();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("\nException: " + ex, nameof(SwapChainSurface) + '.' + nameof(OnNewSurfaceAvailable));
}
rendering = false;
}
OnSurfaceAvailable2 is called from:
void VideoFrameArrived(Bgra32VideoFrame frame)
{
DispatcherQueue.TryEnqueue(() =>
{
previewSurface.OnNewSurfaceAvailable2((device, context) =>
{
var size = frame.m_height * frame.m_height * 4;
D3D11_TEXTURE2D_DESC td;
td.ArraySize = 1;
td.BindFlags = (uint) D3D11_BIND_FLAG.D3D11_BIND_SHADER_RESOURCE;
td.Usage = D3D11_USAGE.D3D11_USAGE_DYNAMIC;
td.CPUAccessFlags = (uint) D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_WRITE;
td.Format = DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM;
td.Height = (uint) frame.m_height;
td.Width = (uint) frame.m_width;
td.MipLevels = 1;
td.MiscFlags = 0;
td.SampleDesc.Count = 1;
td.SampleDesc.Quality = 0;
D3D11_SUBRESOURCE_DATA srd;
srd.pSysMem = frame.m_pixelBuffer;
srd.SysMemPitch = (uint) frame.m_height;
srd.SysMemSlicePitch = 0;
var texture = device.CreateTexture2D<ID3D11Texture2D>(td, new []{srd});
var mappedResource = context.Map(texture.Object, 0, D3D11_MAP.D3D11_MAP_WRITE_DISCARD);
var mappedData = mappedResource.pData;
unsafe
{
Buffer.MemoryCopy(frame.m_pixelBuffer.ToPointer(), mappedData.ToPointer(), size, size);
}
// Just for debug
var pixelsInFrame = new byte[size];
var pixelsInResource = new byte[size];
Marshal.Copy(frame.m_pixelBuffer, pixelsInFrame, 0, size);
Marshal.Copy(mappedResource.pData, pixelsInResource, 0, size);
context.Unmap(texture.Object, 0);
});
});
}
Problem is that I can't see anything rendered and surface stay black and I assume it should not be.
Update: Project repository
Update 2:
I solved my issue. I had too little knowledge about DX11 so I had to study more how things work there. With this knowledge I updated repository which can display preview from black magic design card. It is just example with many issues so be careful and feel free to look for or inspiration there.
There's a various amount of issues here.
First on frame arrived, you have
var texture = device.CreateTexture2D<ID3D11Texture2D>(td, new []{srd});
So your create a texture, but you do not use it anywhere, it needs to be blitted to the swapchain (can do a CopyResource on device context or draw a full screen triangle/quad).
Note that CopyResource will only work if your swapchain has the same size as your incoming texture, which is rather unlikely, so you will have to draw a blit with a shader most likely.
Also you actually copying the data in the texture twice :
var texture = device.CreateTexture2D<ID3D11Texture2D>(td, new []{srd});
Since you provide initial data, the content is already there.
also, pitch is incorrect :
srd.SysMemPitch = (uint) frame.m_height;
pitch is the length (in bytes) of a line, so it should be :
srd.SysMemPitch = frame.GetRowBytes();
Please also note that in case of a non converted Decklink frame,
GetRowBytes can be different from width*4 (they can align row size to multiple of 16/32 or other values).
Next, in the case of resource map, the following is also incorrect :
unsafe
{
Buffer.MemoryCopy(frame.m_pixelBuffer.ToPointer(), mappedData.ToPointer(), size, size);
}
You are not checking the pitch/stride requirement of a texture (which can be different as well),
so you need to do :
if (mappedResource.RowPitch == frame.GetRowBytes())
{
//here you can use a direct copy as above
}
else
{
//here you need to copy data line per line
}
I have a function called: DisplayAndSaveImageFromByteArray.
by its name you probably understand what i am trying to do. In the bytearray the values are pixeldata. so like this 255,220,130,0, etc..
The size of the byte is the Width and the Height of the image times 4.
because it works with strides.
public void DisplayAndSaveImageFromByteArray(byte[] byteArray)
{
try{
byte[] data = new byte[width * height * 4];
int o = 0;
for (int io = 0; io < width * height; io++){
byte value = byteArray[io];
data[o++] = value;
data[o++] = value;
data[o++] = value;
data[o++] = 0;
}
unsafe
{
fixed (byte* ptr = data)
{
using (image = new Bitmap((int)width, (int)height, (int)width * 4,System.Drawing.Imaging.PixelFormat.Format32bppRgb, new IntPtr(ptr)))
{
image.Save(#"c:\\testmap\" + nextpicture + ".jpg", ImageFormat.Jpeg);
if (nextpicture >= 10)
{
pbCameraPreview.BeginInvoke(new InvokeDelegate(InvokeMethod));
}
nextpicture++;
}
}
}
}
catch (Exception ex){
MessageBox.Show(ex.ToString());
}
}
When i run this code it will work, but only if all values are the same for example: White (255,255,255) or Black (0,0,0).
it is able to deviate about 5 up and down in the RGB(A) values until it will stop working.
But as soon as the color of the image changes it will stop working without giving me an Exception of anything.
The only error/Exception i will get it if i leave it on for a minute and the VS will recognize that the code being executed is not doing anything and will give me a warning. > ContextSwitchDeadlock
What did i do wrong for it to crash?
and what is the solution for it?
for some reason it wont let me put on the using and namespace name...
(updated)Complete code:
public Form1()
{
InitializeComponent();
pbCameraPreview.Image = defImg;
}
#region Global
int ii;
object __p1;
EventArgs __p2;
string path;
Image defImg = Image.FromFile(#"c:\\testimg\def.jpg");
UInt32 width;
UInt32 height;
int nextpicture = 0;
FGNodeInfoContainer InfoContainer = new FGNodeInfoContainer();
FGNodeInfo NodeInfo = new FGNodeInfo();
FireWrap_CtrlCenter CtrlCenter;
enFireWrapResult Result;
UInt32 XSize = new UInt32();
UInt32 YSize = new UInt32();
UInt32 NodeCnt;
public delegate void InvokeDelegate();
Bitmap image;
CameraCode Cam = new CameraCode();
FGFrame Frame = new FGFrame();
FGUIntHL Guid = new FGUIntHL();
#endregion
public void CheckDirectory()
{
path = #"c:\\testmap\" + ii + "\\";
if (Directory.Exists(#"c:\\testmap\") == false)
{
Directory.CreateDirectory(#"c:\\testmap\");
}
if (Directory.Exists(path))
{
if (File.Exists(path + "0.Jpeg"))
{
ii++;
CheckDirectory();
}
}
else
{
Directory.CreateDirectory(path);
}
}
//Haal de images op
/// <param name="__p1"></param>
/// <param name="__p2"></param>
public void btStart_Click(object sender, EventArgs e)
{
Debug.WriteLine("btStart_Click is clicked");
// Init module
CtrlCenter = FireWrap_CtrlCenter.GetInstance();
Result = CtrlCenter.FGInitModule();
// Register frame start event
CtrlCenter.OnFrameReady += new FireWrap_CtrlCenter.FireWrapEvent(OnFrameReady);
// Get list of connected nodes
if (Result == enFireWrapResult.E_NOERROR)
{
Result = InfoContainer.FGGetNodeList();
NodeCnt = InfoContainer.Size();
// Print Nodecnt
Console.WriteLine(NodeCnt.ToString() + " camera found");
// Connect with first node
InfoContainer.GetAt(NodeInfo, 0);
Result = Cam.Connect(NodeInfo.Guid);
if (Result == enFireWrapResult.E_NOERROR)
{
Cam.m_Guid = NodeInfo.Guid;
}
// Set Format7 Mode0 Y8
if (Result == enFireWrapResult.E_NOERROR)
{
Result = Cam.SetParameter(enFGParameter.E_IMAGEFORMAT,
(uint)(((uint)enFGResolution.E_RES_SCALABLE << 16) |
((uint)enColorMode.E_CCOLORMODE_Y8 << 8) |
0));
}
if (Result != enFireWrapResult.E_NOERROR)
{
Result = Cam.SetParameter(enFGParameter.E_IMAGEFORMAT,
(uint)(((uint)enFGResolution.E_RES_SCALABLE << 16) |
((uint)enColorMode.E_CCOLORMODE_Y8 << 8) |
1));
}
// Start DMA logic
if (Result == enFireWrapResult.E_NOERROR)
Result = Cam.OpenCapture();
// Print device settings
Result = Cam.GetParameter(enFGParameter.E_XSIZE, ref XSize);
Result = Cam.GetParameter(enFGParameter.E_YSIZE, ref YSize);
Debug.WriteLine(Cam.DeviceAll + " [" + Cam.m_Guid.Low.ToString() + "] " + XSize + "x" + YSize);
width = XSize;
height = YSize;
// Start camera
if (Result == enFireWrapResult.E_NOERROR)
{
Result = Cam.StartDevice();
}
}
}
public void btStop_Click(object sender, EventArgs e)
{
// Stop the device
Cam.StopDevice();
// Close capture
Cam.CloseCapture();
// Disconnect before ExitModule
Cam.Disconnect();
// Exit module
CtrlCenter.FGExitModule();
}
/// <param name="__p1"></param>
/// <param name="__p2"></param>
public void OnFrameReady(object __p1, EventArgs __p2)
{
Debug.WriteLine("OnFrameReady is called");
FGEventArgs args = (FGEventArgs)__p2;
Guid.High = args.High;
Guid.Low = args.Low;
if (Guid.Low == Cam.m_Guid.Low)
{
Result = Cam.GetFrame(Frame, 0);
// Process frame, skip FrameStart notification
if (Result == enFireWrapResult.E_NOERROR & Frame.Length > 0)
{
byte[] data = new byte[Frame.Length];
// Access to frame data
if (Frame.CloneData(data))
{
DisplayAndSaveImageFromByteArray(data);
// Here you can start your image processsing logic on data
string debug = String.Format("[{6}] Frame #{0} length:{1}byte [ {2} {3} {4} {5} ... ]",
Frame.Id, Frame.Length, data[0], data[1], data[2], data[3], Cam.m_Guid.Low);
Debug.WriteLine(debug);
}
// Return frame to module as fast as posible after this the Frame is not valid
Result = Cam.PutFrame(Frame);
}
}
}
public void DisplayAndSaveImageFromByteArray(byte[] byteArray)
{
try{
byte[] data = new byte[width * height * 4];
int o = 0;
for (int io = 0; io < width * height; io++){
byte value = byteArray[io];
data[o++] = value;
data[o++] = value;
data[o++] = value;
data[o++] = 0;
}
unsafe
{
fixed (byte* ptr = data)
{
using (image = new Bitmap((int)width, (int)height, (int)width * 4,System.Drawing.Imaging.PixelFormat.Format32bppRgb, new IntPtr(ptr)))
{
image.Save(#"c:\\testmap\" + nextpicture + ".jpg", ImageFormat.Jpeg);
if (nextpicture >= 10)
{
pbCameraPreview.BeginInvoke(new InvokeDelegate(InvokeMethod));
}
nextpicture++;
}
}
}
}
catch (Exception ex){
MessageBox.Show(ex.ToString());
}
}
public void InvokeMethod()
{
pbCameraPreview.Image = Image.FromFile(#"c:\\testmap\" + (nextpicture -10) + ".jpg");
}
}
public class CameraCode : FireWrap_Camera
{
public FGUIntHL m_Guid;
}}
Threads running:
I recorded it for extra information:
https://www.youtube.com/watch?v=i3TxWRyZaIU
I'm not 100% sure that I have understood your problem, since it is not very clear the format of the input array and how do you have to format it before parsing it into the Bitmap variable... But here we go, I hope these tips can help you. If they don't, please try to provide some extra details on what you are trying to do.
First of all, if I have understood well, you should increase "io" and update the variable "value" each time you assign it to data[o++] in the main loop, otherwise you are assigning the same value to R, G and B pixels, which will always result in a shade of gray.
Secondly, I see a couple things in your code that are not very .net-ly... .Net provides already ways to load an image from a byte array, using Memory Streams and stuff. Take a look at How to create bitmap from byte array?
And be sure to indicate the proper format of your byte array image when instantiating the Bitmap or Image --> https://msdn.microsoft.com/en-us/library/system.drawing.imaging.pixelformat(v=vs.110).aspx
Regards.
If you have trouble posting your code in StackOverflow, make sure each line is indented by at least 4 spaces (mark the code in Visual Studio, press Tab, then copy it) and separated by any other paragraphs by at least one empty line. Alternatively add a line of three backticks (`) at the beginning and and of the code.
When looking at your code, it seems to me that you are using a third-party control inside a Windows Form and try to bind the event of it to one of your Windows Forms event handlers. In that case you have to be aware that Windows Forms expect that all events are handled single-threaded (in the Event Dispatch Thread), so you should check (Debug.WriteLine) in your OnFrameReady method if InvokeRequired is true and if yes you have to take a few precautions:
Never access any of the Form's internal members (like pbCameraPreview) without wrapping the call into Invoke or BeginInvoke. Keep in mind that every Invoke call will effectively block until the single event-dispatch thread is available, so it will cost you a lot of performance to do invoke synchronously.
When accessing your own members (like width, height or nextpicture), make sure you use appropriate locking to avoid situations where one thread/callback changes the value in a situation where you don't expect it. In particular, since you have multiple cams but only a single width/height variable, if the resolutions differ, one camera callback could change the width while the other camera callback has just allocated the byte array but before passing the width to the Bitmap constructor, most likely resulting in a hang, crash, or memory access violation. Avoid this by passing width and heigth as variables into your method instead of using the global ones.
Your form's event handler (btStart_Click) contains a busy-wait loop. This has multiple problems:
As stated before, every Form event handler runs in the same thread (and every Invoke as well). So as long as your loop is busy-waiting, no other events can be handled and the UI will be completely frozen. If code uses Invoke, that code will also eventually have to wait and be blocked, too.
Busy wait loops without any sleep code in it will cause your processor to run at the full cpu speed and it will eat 100% of that core, causing battery drain on notebooks and high power consumption and probably loud fans on other machines. Just don't do that.
In your concrete example, just remove the loop and move everything after the loop into the stop button instead. To avoid the problems with Windows Forms and invoking, I'd suggest to put all the image handling logic into a separate class that does its own locking (each instance of the class handling one camera only), and just call into it to start the process. You might even prefer to do your app as a Console application first to avoid any event-dispatching issues and later convert it to a Windows Forms application once it is working as you desire.
I have been exhausted from this error from last 2 weeks.I tried a lot to find out and tried the code in different way but not succeeded yet.I think the main problem is with bitmap, may be i am not using in right way.I am sharing my code for help to understand what i am doing.
First i tell you the scenario.In this app, i am using dslr camera for live view.The main code area from camera class is here below :
internal void Run()
{
LVrunning = true;
while (LVrunning)
{
Thread.Sleep(20);
if (LVrunning)
UpdatePicture();
}
}
private void UpdatePicture()
{
try
{
if (err == EDSDK.EDS_ERR_OK && LVrunning)
{
inSide = true;
// Download live view image data
err = EDSDK.EdsDownloadEvfImage(cameraDev, EvfImageRef);
if (err != EDSDK.EDS_ERR_OK)
{
Debug.WriteLine(String.Format("Download of Evf Image: {0:X}", err));
return;
}
IntPtr ipData;
err = EDSDK.EdsGetPointer(MemStreamRef, out ipData);
if (err != EDSDK.EDS_ERR_OK)
{
Debug.WriteLine(String.Format("EdsGetPointer failed: {0:X}", err));
return;
}
uint len;
err = EDSDK.EdsGetLength(MemStreamRef, out len);
if (err != EDSDK.EDS_ERR_OK)
{
Debug.WriteLine(String.Format("EdsGetLength failed:{0:X}", err));
EDSDK.EdsRelease(ipData);
return;
}
Byte[] data = new byte[len];
Marshal.Copy(ipData, data, 0, (int)len);
System.IO.MemoryStream memStream = new System.IO.MemoryStream(data);
// get the bitmap
Bitmap bitmap = null;
try
{
bitmap = new Bitmap(memStream);
}
catch (OutOfMemoryException ex)
{
GC.WaitForPendingFinalizers();
bitmap = new Bitmap(memStream); // sometimes error occur
}
NewFrame(bitmap, null); // this is event call back to form area.
memStream.Dispose();
EDSDK.EdsRelease(ipData);
}
}
catch (Exception ex)
{
}
}
private void getCapturedItem(IntPtr directoryItem)
{
uint err = EDSDK.EDS_ERR_OK;
IntPtr stream = IntPtr.Zero;
EDSDK.EdsDirectoryItemInfo dirItemInfo;
err = EDSDK.EdsGetDirectoryItemInfo(directoryItem, out dirItemInfo);
if (err != EDSDK.EDS_ERR_OK)
{
throw new CameraException("Unable to get captured item info!", err);
}
// Fill the stream with the resulting image
if (err == EDSDK.EDS_ERR_OK)
{
err = EDSDK.EdsCreateMemoryStream((uint)dirItemInfo.Size, out stream);
}
// Copy the stream to a byte[] and
if (err == EDSDK.EDS_ERR_OK)
{
err = EDSDK.EdsDownload(directoryItem, (uint)dirItemInfo.Size, stream);
}
// Create the returned item
//CapturedItem item = new CapturedItem();
if (dirItemInfo.szFileName.ToString().ToLower().Contains("jpg") || dirItemInfo.szFileName.ToString().ToLower().Contains("jpeg"))
{
if (err == EDSDK.EDS_ERR_OK)
{
IntPtr imageRef = IntPtr.Zero;
err = EDSDK.EdsCreateImageRef(stream, out imageRef);
if (err == EDSDK.EDS_ERR_OK)
{
EDSDK.EdsImageInfo info;
err = EDSDK.EdsGetImageInfo(imageRef, EDSDK.EdsImageSource.FullView, out info);
}
}
}
if (err == EDSDK.EDS_ERR_OK)
{
try
{
byte[] buffer = new byte[(int)dirItemInfo.Size];
GCHandle gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
IntPtr address = gcHandle.AddrOfPinnedObject();
IntPtr streamPtr = IntPtr.Zero;
err = EDSDK.EdsGetPointer(stream, out streamPtr);
if (err != EDSDK.EDS_ERR_OK)
{
throw new CameraDownloadException("Unable to get resultant image.", err);
}
try
{
Marshal.Copy(streamPtr, buffer, 0, (int)dirItemInfo.Size);//sometimes error comes here
System.IO.MemoryStream memStream = new System.IO.MemoryStream(buffer);
Bitmap bitmap = null;
try
{
bitmap = new Bitmap(memStream);
}
catch (OutOfMemoryException ex)
{
GC.WaitForPendingFinalizers();
Bitmap b = new Bitmap(memStream);//sometimes error comes here
}
if (bitmap != null)
{
PhotoCaptured(bitmap, null);
}
}
catch (AccessViolationException ave)
{
throw new CameraDownloadException("Error copying unmanaged stream to managed byte[].", ave);
}
finally
{
gcHandle.Free();
EDSDK.EdsRelease(stream);
EDSDK.EdsRelease(streamPtr);
}
}
catch (OutOfMemoryException ex)
{
GC.WaitForPendingFinalizers();
IboothmeObject.minimizeMemory();
getCapturedItem(directoryItem);
}
}
else
{
throw new CameraDownloadException("Unable to get resultant image.", err);
}
}
On form side, image is updating in picture box simply
private void StartLiveView()
{
if (this.liveView.Connected)
{
this.liveView.PhotoCaptured += new EventHandler(liveView_PhotoCaptured);
this.liveView.NewFrame += new EventHandler(liveView_NewFrame);
this.liveView.StartLiveView();
}
}
void liveView_NewFrame(object sender, EventArgs e)
{
this.picMain.Image = sender as Image;
}
void liveView_PhotoCaptured(object sender, EventArgs e)
{
Image img = sender as Image;
// this image is big in size like 5000x3000.
Bitmap tempbitmap = new Bitmap(img.Width, img.Height);// now mostly error comes here
tempbitmap.SetResolution(img.HorizontalResolution, img.VerticalResolution);
using (Graphics g = Graphics.FromImage(tempbitmap))
{
g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height));
g.Save();
}
picMain.Image = tempbitmap;
tempbitmap.Save(path,ImageFormat.Jpeg);
}
Another area of code which uses the bitmap and live view from camera.This code get the frame from camera and write some objects on frame..In my case, i am writing some ballons on the frame
void liveView_NewFrame(object sender, EventArgs e)
{
using (Image<Bgr, byte> Frame = new Image<Bgr, byte>(new Bitmap(sender as Image)))
{
Frame._SmoothGaussian(3);
IntPtr hsvImage = CvInvoke.cvCreateImage(CvInvoke.cvGetSize(Frame), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 3);
CvInvoke.cvCvtColor(Frame, hsvImage, Emgu.CV.CvEnum.COLOR_CONVERSION.CV_BGR2HSV);
Image<Gray, byte> imgThresh = new Image<Gray, byte>(Frame.Size);
imgThresh.Ptr = GetThresholdedImage(hsvImage);
//CvInvoke.cvSmooth(imgThresh, imgThresh, Emgu.CV.CvEnum.SMOOTH_TYPE.CV_GAUSSIAN, 3, 3, 3, 3);
#region Draw the contours of difference
//this is tasken from the ShapeDetection Example
Rectangle largest = new Rectangle();
try
{
using (MemStorage storage = new MemStorage()) //allocate storage for contour approximation
//detect the contours and loop through each of them
for (Contour<Point> contours = imgThresh.Convert<Gray, Byte>().FindContours(
Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL,
storage);
contours != null;
contours = contours.HNext)
{
//Create a contour for the current variable for us to work with
Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage);
//Draw the detected contour on the image
if (currentContour.Area > ContourThresh) //only consider contours with area greater than 100 as default then take from form control
{
if (currentContour.BoundingRectangle.Width > largest.Width && currentContour.BoundingRectangle.Height > largest.Height)
{
largest = currentContour.BoundingRectangle;
}
}
//storage.Dispose();
}
}
catch (Exception)
{
}
#endregion
#region Draw Object
Random r = new Random();
//Bitmap bb = Frame.Bitmap;
foreach (var item in objectList)
{
using (Graphics g = Graphics.FromImage(Frame.Bitmap))
{
if (DrawAble(item, largest))
{
if (item.Y < 0)
{
if (item.X < picMain.Width)
{
g.DrawImage(item.image, new Rectangle(item.X, 0, item.image.Width, item.image.Height + item.Y),
new Rectangle(), GraphicsUnit.Pixel);
item.X += r.Next(-5, 5);
item.Y += 15;
}
}
else
{
if (item.X < picMain.Width && item.Y < picMain.Height)
{
g.DrawImage(item.image, new Rectangle(item.X, item.Y, item.image.Width, item.image.Height));
item.X += r.Next(-5, 5);
item.Y += 15;
}
else
{
item.X = r.Next(0, picMain.Width - 5);
item.Y = r.Next(-item.image.Height, -5);
}
}
}
else
{
item.X = r.Next(0, picMain.Width - 5);
item.Y = r.Next(-item.image.Height, -5);
}
}
}
#endregion
picMain.Image = Frame.ToBitmap();
}
minimizeMemory();
}
Now i share the whole problem in detail.
First on all i created a form for live view and by using opencv(Emgu) library , i am drawing balloons on the frame.In live view these balloons are moving.The other form is for capture the picture from camera with high resolution.
I noticed that, my application memory was increasing with every frame and after 2 live-view and 2 pictures caputured, it goes to 1+ GB.If i tried to show first form again for live view, error occured in UpdatePicture() function.
then i add the code to minimize the memory of the current application.now i am calling this function after every frame in live-view.
After this solution when i checked the memory of application it does not go over 100mb or 200mb.
But problem was still there.after few captures, error occurred in UpdatePicture() when get bitmap from stream ( bitmap = new Bitmap(memStream);).The error was same out of memory.
After some search i found this solution.
// get the bitmap
Bitmap bitmap = null;
try
{
bitmap = new Bitmap(memStream);
}
catch (OutOfMemoryException ex)
{
GC.WaitForPendingFinalizers();
bitmap = new Bitmap(memStream);
}
But not working error is still same.
Error sometimes shown in UpdatePicture() method, sometime occurred in liveView_NewFrame method.
Means problem is related to bitmap, bitmap size or memory is corrupt.
So please help me.I am worried, 2 weeks passed but i could not solve this.
you are calling CvInvoke.cvCreateImage the created data is sitting on the native heap
so it wont be collected by the GC.
you must call cvReleaseImage(IntPtr) to release the data
there are alot of memory profilers which can help understanding the issue
try using ANTS Memory Profiler 7
I am developing an app with Mono for Android.
I have been struggling with Out of memory exceptions for the last few days and am starting to lose hope!
I have a ListView displaying anything from 200 to 600 items. These items consist of a bitmap thumbnail and some text.
I am decoding the Bitmap asynchronously using an AsyncTask, here is the code:
public class BitmapWorkerTask : AsyncTask
{
private WeakReference imageViewReference;
public string thisURL = "";
private int sampleSize = 0;
private int reqHeight = 0;
private int reqWidht = 0;
public BitmapWorkerTask(ImageView imageView, int pSampleSize, int pReqWidth, int pReqHeight)
{
//_____________________________________________________________________
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference(imageView);
reqHeight = pReqHeight;
reqWidht = pReqWidth;
sampleSize = pSampleSize;
}
protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] #params)
{
string strUrl = #params[0].ToString();
try
{
return DecodeSampleBitmapFromStream(strUrl, reqWidht, reqHeight);
}
catch (Exception ex)
{
return null;
}
}
protected override void OnPostExecute(Java.Lang.Object result)
{
base.OnPostExecute(result);
if (IsCancelled)
{
result = null;
Log.Debug("TT", "OnPostExecute - Task Cancelled");
}
else
{
Bitmap bmpResult = result as Bitmap;
if (imageViewReference != null && bmpResult != null)
{
ImageView view = imageViewReference.Target as ImageView;
if (view != null)
{
view.SetImageBitmap(bmpResult);
}
}
}
}
public static int CalculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight)
{
//_____________________________
// Raw height and width of image
int height = options.OutHeight;
int width = options.OutWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth)
{
if (width > height)
{
inSampleSize = (int)Math.Round((float)height / (float)reqHeight);
}
else
{
inSampleSize = (int)Math.Round((float)width / (float)reqWidth);
}
}
return inSampleSize;
}
public static Bitmap DecodeSampleBitmapFromStream(string URL, int reqWidth, int reqHeight)
{
URL url = new URL(URL);
try
{
//______________________________________________________________
// First decode with inJustDecodeBounds=true to check dimensions
BitmapFactory.Options options = new BitmapFactory.Options();
options.InJustDecodeBounds = true;
BitmapFactory.DecodeStream(url.OpenConnection().InputStream, null, options);
//______________________
// Calculate inSampleSize
options.InSampleSize = CalculateInSampleSize(options, reqWidth, reqHeight);
//____________________________________
// Decode bitmap with inSampleSize set
options.InJustDecodeBounds = false;
return BitmapFactory.DecodeStream(url.OpenConnection().InputStream, null, options);
}
catch (Exception ex)
{
return null;
}
finally
{
url.Dispose();
}
}
I am starting this AsyncTask from the Lists GetView() function using this Method:
public void loadBitmap(string url, ImageView imageView)
{
if (Common.cancelPotentialWork(url, imageView))
{
BitmapWorkerTask task = new BitmapWorkerTask(imageView, 2, 80,80);
AsyncDrawable asyncDrawable = new AsyncDrawable(null, null, task);
imageView.SetImageDrawable(asyncDrawable);
task.Execute(url);
}
}
Everything works as expected for a period of time, but if I continuously scroll up and down through my list I eventually start getting OutOfMemoryExceptions and the app crashes. My understanding of how the Android list works is it disposes of the ListItem views as they move off screen, but it feels as though this is not happening!
It feels like all those bitmaps I am decoding as I scroll through the list are for whatever reason being held in memory? What could I be missing here that is preventing those bitmaps from being disposed of? Where could I implement a call to Bitmap.Recycle() to ensure the bitmaps are cleared?
I did a test whereby I made a call to GC.Collect on every call to GetView which did seem to keep my memory usage fairly consistent, but I know this shouldn't be needed and it affects scrolling performance.
Why when I scroll through my list without the call to GC.Collect() am I not seeing those garbage collection message indicating that the system is, in fact, doing routine collections?
Any help is appreciated, I am losing the will to code!
My understanding of how the Android list works is it disposes of the List item views as they move off screen, but It feels as though this is not happening!
This isn't correct.
What Android does is it hold on to the set of item views and it tries to reuse them after they have gone off screen. This is what the convertView parameter is for.
I can't see your Adapter code posted in the question, so I'm not sure what your code is for using the convertView parameter, but I'd guess what it should do in the case of a convertView is:
it should cancel any existing async image fetch/conversion
it should start a new one
The MvvmCross code may be a little too complicated for you as a reference/example here, but you can at least see convertView in use in MvxBindableListAdapter.cs - see protected virtual View GetBindableView(View convertView, object source, int templateId)
I am using WPF to display the image in the clipboard. This works fine when going to Paint and copying something there, but when I hit "Print screen" to take a screenshot, the output there is just a black image, that has the same dimensions as the screen.
How come?
The code for taking data from the clipboard is as follows (yes, I do in fact want to use raw API calls).
...
case CF_BITMAP:
BitmapSource source = null;
System.Drawing.Bitmap finalBitmap = null;
IntPtr destinationHdc = CreateCompatibleDC(IntPtr.Zero);
if (destinationHdc != null)
{
IntPtr sourceHdc = CreateCompatibleDC(IntPtr.Zero);
if (sourceHdc != null)
{
if (OpenClipboard(MainWindow.Handle))
{
IntPtr sourceBitmap = GetClipboardData((uint)clipboardFormat);
SelectObject(sourceHdc, sourceBitmap);
BITMAP bmp;
GetObject(sourceBitmap, Marshal.SizeOf(typeof(BITMAP)), out bmp);
IntPtr destinationBitmap = CreateCompatibleBitmap(destinationHdc, bmp.bmWidth, bmp.bmHeight);
SelectObject(destinationHdc, destinationBitmap);
BitBlt(destinationHdc, 0, 0, bmp.bmWidth, bmp.bmHeight, sourceHdc, 0, 0, 0x00CC0020);
CloseClipboard();
finalBitmap = System.Drawing.Bitmap.FromHbitmap(destinationBitmap);
}
DeleteDC(sourceHdc);
}
DeleteDC(destinationHdc);
}
if (finalBitmap != null && ((LastData == null || !(LastData is System.Drawing.Bitmap)) || !finalBitmap.EqualsTo((System.Drawing.Bitmap)LastData)))
{
source = BitmapToSource(finalBitmap);
if (LastData == null || source != LastData)
{
tile = new ImageTile();
(tile as ImageTile).Image.Source = source;
tile.RawData = finalBitmap;
}
}
return tile;
...
I ended up using the inbuilt framework method instead, Clipboard.GetImage(). The WPF version of it seems to work better than the Windows Forms one.