AccessViolationException when converting chart to image

Hello.

I sometimes get an AccessViolation Exception when trying to convert charts to images using Apose Cells.

Exception Info: System.AccessViolationException
Stack:
at System.Drawing.SafeNativeMethods+Gdip.IntGdipDisposeImage(System.Runtime.InteropServices.HandleRef)
at System.Drawing.SafeNativeMethods+Gdip.IntGdipDisposeImage(System.Runtime.InteropServices.HandleRef)
at System.Drawing.Image.Dispose(Boolean)
at System.Drawing.Image.Dispose()
at €“..š›()
at Aspose.Cells.Charts.Chart.ToImage(System.IO.Stream, Aspose.Cells.Rendering.ImageOrPrintOptions)

The code that produces this is the following:

 	//using (var lMs = new MemoryStream()) // This may cause an "Out of memory" exception. See : http://stackoverflow.com/a/7776404, http://msdn.microsoft.com/en-us/library/93z9ee4x.aspx
	var lMs = new MemoryStream();
	{
 		var opt = new Aspose.Cells.Rendering.ImageOrPrintOptions() { ChartImageType = ImageFormat.Emf, ImageFormat = ImageFormat.Emf, };
 		lCh.ToImage(lMs, opt);
		lMs.Position = 0;
		lBits.Add(Image.FromStream(lMs));
	}
I don't know, yet, if using this code instead will make any difference:
	//using (var lMs = new MemoryStream()) // This may cause an "Out of memory" exception. See : http://stackoverflow.com/a/7776404, http://msdn.microsoft.com/en-us/library/93z9ee4x.aspx
	var lMs = new MemoryStream();
	{
		lCh.ToImage(lMs, ImageFormat.Emf);
		lMs.Position = 0;
		lBits.Add(Image.FromStream(lMs));
	}

Do you have any thoughts on the subject?

Best Regards,
Kostas

Hi,

Thanks for your posting and using Aspose.Cells for .NET.

Please download and try the latest version: Aspose.Cells
for .NET v7.5.0.4
and see if it resolves your issue.

If your problem still persists, then please provide us your source file and the runnable sample code replicating this issue with the latest version. We will look into it and help you asap.

Hello.


I came across another exception (Object reference not set to an instance of an object) while converting a chart to image.
I am sending you a sample app that uses Aspose.Cells for .NET v7.5.0.4 and reads a chart from an XLSX file and tries to make it an image.

Here is the sample’s code:

			var loadOptions = new LoadOptions(LoadFormat.Xlsx);
var dataOption = new LoadDataOption();
dataOption.ImportFormula = true;
loadOptions.LoadDataOnly = false;
loadOptions.LoadDataOptions = dataOption;
Workbook wb = new Workbook(@“C:\Users.…\Survey.xlsx”, loadOptions);

		<span style="color:blue;">var</span> sheet = wb.Worksheets[0];
		<span style="color:blue;">var</span> chart = sheet.Charts[0]; <pre style="font-family: Consolas; background-position: initial initial; background-repeat: initial initial;">			lCh.PrintSize = <span style="color:#2b91af;">PrintSizeType</span>.Custom;
		lCh.ChartObject.Height = 280;
		lCh.ChartObject.Width = 400;
		lCh.ChartArea.Border.IsVisible = <span style="color:blue;">false</span>; <span style="color:green;">// Remove border.</span>
		<span style="color:blue;">if</span> (lCh.CategoryAxis != <span style="color:blue;">null</span>) lCh.CategoryAxis.TickLabels.RotationAngle = 0;
		<span style="color:blue;">try</span> { lCh.Calculate(); }</pre>
		<span style="color:blue;">var</span> lMs = <span style="color:blue;">new</span> <span style="color:#2b91af;">MemoryStream</span>();
		{
			chart.ToImage(lMs, <span style="color:#2b91af;">ImageFormat</span>.Emf);
			lMs.Position = 0;
			<span style="color:blue;">var</span> img = <span style="color:#2b91af;">Image</span>.FromStream(lMs);
		}</pre></div><div><br></div><div>With this you will be able to reproduce the new exception that I get. The chart has over 690 categories. I don't know if this is causing some problems. But I have the impression that only the number of series of the chart is limitted to 256 series maxmum, right?<br>I have noticed that when I specify small dimensions for the image, I get no exception.<br>But I want my image to be large.</div><div><br></div><div>Note that both methods <span style="font-family: Consolas; font-size: 13px;">Calculate() and </span><span style="background-color: white; font-family: Consolas; font-size: 13px;">ToImage() </span>throw an exception:</div><div><br>{"Object reference not set to an instance of an object."}</div><div><span style="background-color: white; font-family: Consolas; font-size: 13px;"><div>   at    .   .   (    , String , Int32 , Font , SizeF ,     ,     )</div><div>   at    .   .   (    ,     , Rectangle , Rectangle , Int32 , Boolean ,     )</div><div>   at    .   .Calculate(    )</div><div>   at    .   .   (    )</div><div>   at    .   .Calculate()</div><div>   at    .   .   (Chart )</div><div>   at    .   .   (Chart , Boolean )</div><div>   at    .   .Calculate(Chart , Boolean )</div><div>   at Aspose.Cells.Charts.Chart.Calculate(Boolean , Boolean )</div><div>   at Aspose.Cells.Charts.Chart.Calculate()</div><div>   at del7.Form1.button1_Click(Object sender, EventArgs e) in c:\Users\...\del7\del7\Form1.cs:line 34</div><div><br></div></span></div><div><span style="background-color: white; font-family: Consolas; font-size: 13px;"><br></span></div><div><span style="background-color: white; font-family: Consolas; font-size: 13px;"><div>   at    .   .   (    , String , Int32 , Font , SizeF ,     ,     )</div><div>   at    .   .   (    ,     , Rectangle , Rectangle , Int32 , Boolean ,     )</div><div>   at    .   .Calculate(    )</div><div>   at    .   .   (    )</div><div>   at    .   .   ()</div><div>   at    .   .   ()</div><div>   at    .   .ToImage(Stream , ImageFormat , Chart )</div><div>   at Aspose.Cells.Charts.Chart.ToImage(Stream stream, ImageFormat imageFormat)</div><div>   at del7.Form1.button1_Click(Object sender, EventArgs e) in c:\Users\...\del7\del7\Form1.cs:line 39</div></span></div><div><br></div><div>Please, let me know of any workarounds or fixes to this.</div><div><br></div><div>Best Regards,</div><div>Kostas</div></div>

Hi,


Thanks for providing us the sample project with the template file.

After an initial test as I have tested your code with your template file and found the exception:
“Object reference not set to an instance of an object.” on rendering chart to an image file. I have logged a ticket with an id “CELLSNET-41808” for your issue. We will look into your issue soon.

Once we have any update on it, we will let you know here.

Thank you.


Hello there,

I am experiencing exact same issue (Object reference not set to an instance of an objectv) while exporting charts with say 200 categories.

This is causing big problem for us as we are already live with ASPOSE components on production.

Any quick fix will be really appreciated.

Thanks

Imran

Hi Imran,


Well, as we have logged a ticket with an id “CELLSNET-41808” for the issue. We will surely look into your issue soon. Once we figure it out, we may either provide some workaround or attach a fix here, you may try it and let us know.

Thank you.

Hello.


I have an update:
It seems that the exception doesn’t appear when I remove the following line:
if (lCh.CategoryAxis != null) lCh.CategoryAxis.TickLabels.RotationAngle = 0;
But there is a reason that I have this line.
A display bug appears when not added (sometimes the tick labels get rotated at 90 degree angle when converting to image).
I can’t have this random behaviour, that’s why I set the rotation angle to 0.
Why does this generate the problem?
Best Regards,
Kostas

In fact, every angle except 0 and 90 doesn’t make the exception to appear.

Why is 0 and 90 creating problems?

Hi,


Thanks for your work and information.

You are right, it does not work when we set TickLables’ rotation angle to 0 or 90, other values work fine though. We have also logged it against your issue “CELLSNET-41808” into our database. We will look into it soon.

Thank you.

Hi,

Thanks for your posting and using Aspose.Cells for .NET.

Please download and try this fix: Aspose.Cells for .NET v7.5.0.5 and let us know your feedback.

The issues you have found earlier (filed as CELLSNET-41808) have been fixed in this update.


This message was posted using Notification2Forum from Downloads module by Aspose Notifier.

Hello.


I have a new case of access violation while trying to convert charts to image:

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

at System.Drawing.SafeNativeMethods.Gdip.GdipFillPath(HandleRef graphics, HandleRef brush, HandleRef path)
at System.Drawing.Graphics.FillPath(Brush brush, GraphicsPath path)
at . . (Brush , GraphicsPath )
at . . (GraphicsPath , Single , GraphicsPath )
at . . (GraphicsPath , Single )
at . . (RectangleF )
at . . (Rectangle )
at . . ()
at . . ()
at . . ()
at . .ToImage(Stream , ImageFormat , Chart )
at Aspose.Cells.Charts.Chart.ToImage(Stream stream, ImageFormat imageFormat)

Target site : {Int32 GdipFillPath(System.Runtime.InteropServices.HandleRef, System.Runtime.InteropServices.HandleRef, System.Runtime.InteropServices.HandleRef)}

It seems that the Chart.ToImage() method is not thread safe.
I attach a demo project that seems to reproduce the error.
(Note: to run the EXE, place the XLSX-es in a folder, set the floder path in the exe and hit the button)
If you run it for some time it will crash with access violation.
It would be great if you could fix that.

Best Regards,
Kostas.

Hi,

Thanks for your posting and using Aspose.Cells for .NET.

Could you please download and try the latest version Aspose.Cells
for .NET v7.5.2.2
and let us know your feedback?

I have tested your issue with the latest version and it generates some different exception. Could you let us know run results at your end? We will log it in our database for a fix.

Hi.


I have just tried the latest version.
I still get crashes. I now got a heap corruption and access violations.

There are some exceptions of “Parameter is not valid.” but those don’t make the app crash (these don’t happen when running the code in one thread either, by the way. I don’t know why.). So, this is a problem too (since normally the Chart.ToImage() should behave the same, no matter how many thread use it).

If you run the program outside of debug mode however, you get crashes (heap corruptions and access violations) not just exceptions and this is a huge problem for a piece of code.

Best Regards,
Kostas

Hi,

Thanks for your feedback and using Aspose.Cells.

We were able to observe the exceptions with v7.5.2 and v7.5.2.2. We have logged this issue in our database for investigation. We will look into it and fix this issue. Once, the issue is resolved or we have some other update for you, we will let you know asap.

This issue has been logged as CELLSNET-41986.

Hi,

Thanks for using Aspose.Cells.

We have checked the project you provided. We found the resources are not released in the project. At the same time it is best saving chart to file, please use Chart.Tomage() directly.

C#

for (int i = 0; i < 10; i++)

{


using (var lMs = new MemoryStream())

{


{


if (lCh.Type == ChartType.Area)

{


bool re = lCh.NSeries.CategoryData == null;


}


lCh.ToImage(lMs, ImageFormat.Emf);




if (lMs.Length != 0)

{


lMs.Position = 0;


using (var img = Image.FromStream(lMs))

{




string bookName = Path.GetFileName(oneXlsx);


string name = @“D:\Aspose\User\0643\del7\File”


+ bookName + “" + lWks.Name + "” + chartIndex.ToString()


+ “_” + i.ToString() + “.emf”;




//Don’t use the for saving chart to file


//img.Save(name, ImageFormat.Emf);




//Use the method to replace the upper


lCh.ToImage(name, ImageFormat.Emf);




//Please release the resource


lMs.Close();


img.Dispose();


}

}

}

}

}

Hello.

Yes, I don’t save the images directly with Chart.Tomage() because this was a simple demo immitating a real project.

In my real project I insert them into a DOCX document.

Also, the reason that I don’t release the memory stream (although here I could) is because in my real project I can’t do it immediately, since MS say so:

Quote: “You must keep the stream open for the lifetime of the Image.”

However, all these have nothing to do with the problem.

Did you find anything concerning the access violations and heap corruptions?
Perhaps it’s a shared static variable or shared (between the threads) object in Aspose Cells that causes this.
This seems to be a threading problem, since it is only reproduced when multiple threads use the convertion to image functionality.
If you make the loop of your code multithreaded it will be crashing again.
Please, find what these threads use in common and you will find the problem.
Normally, they should not use the same objects and if they need to do so they must be synchronized somehow.

Kostas.

Hi,

Thanks for your posting and using Aspose.Cells.

Well, it seems your problem is related to multithreading and not freeing the resources. It is not related to Aspose.Cells. However, we have logged your comment in our database. We will look into it and advise you if possible. Once, we will have some update for you, we will let you know asap.

Hi.


Thanks for the update.

It is not related to Aspose.Cells.

Does this mean that you cannot fix this?
Is it an issue with GDI+ and its wrappers ?
I have found a workaround to avoid crashing but it makes the generation of images TOO slow.
It basically makes my multithreaded system work as a single threaded. :frowning:
I would like to avoid that, so a solution from your end would be very appreciated.

Thanks,
Kostas

Hi,

Thanks for your posting and using Aspose.Cells.

We have already logged your comment in our database. Please spare us some time. Once, there is some fix or update for you, we will let you know asap.